此时情绪此时天,无事小神仙
好好生活,平平淡淡每一天

编辑

Synchronized 锁的错误使用方式及如何解决

synchronized关键字,一般称之为”同步锁“,用它来修饰需要同步的方法和需要同步代码块,默认是当前对象作为锁的对象。

同步锁锁的是同一个对象,如果对象发生改变,则锁会不生效。

锁失败的代码:

public class IntegerSynTest {

    //线程实现Runnable接口
    private static class Worker implements Runnable{

        private Integer num;

        public Worker(Integer num){
            this.num=num;
        }
        @Override
        public void run() {
            
            synchronized (num){
                Thread thread = Thread.currentThread();
                //System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
                System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
                num++;
                System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
            }
        }

        public static void main(String[] args) {
            Worker worker = new Worker(1);
            for (int i = 0; i < 5; i++) {
                new Thread(worker).start();
            }
        }
    }
}

锁失败的运行结果:

锁失败的原因:

1.num++  的  .class  实现是这样的  Integer integer1 = this.num, integer2 = this.num = Integer.valueOf(this.num.intValue() + 1);

2. 查看 Integer.valueOf() 的源代码

 

 这时发现,它是重新 new 出一个新的 Integer,这样的话,每 ++ 一次,那么就会产生一个新的对象,而Synchronize锁是锁同一个对象,当锁不同对象时,则会锁失败。

解决方法:

Synchronized 同步锁只要锁的对象不发生改变即可,那么由此只需要声明一个对象,不修改它,锁这一个对象即可(还有其他方法暂不一一列举,以后也不会列举了)。

锁成功的代码

public class IntegerSynTest {

    //线程实现Runnable接口
    private static class Worker implements Runnable{

        private Integer num;
        /**
         *  ---重点看这里---
         *  声明要锁的对象
         *  ---重点看这里---
         */
        private Object object = new Object();

        public Worker(Integer num){
            this.num=num;
        }
        @Override
        public void run() {
            //修改锁对象
            synchronized (num){
                Thread thread = Thread.currentThread();
                //System.identityHashCode:返回原生的hashCode值,不管Object对象是被重写;空引用的哈希代码为零
                System.out.println(thread.getName()+"--@:---"+System.identityHashCode(num));
                num++;
                System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(thread.getName()+"------num:"+num+"---"+System.identityHashCode(num));
            }
        }

        public static void main(String[] args) {
            Worker worker = new Worker(1);
            for (int i = 0; i < 5; i++) {
                new Thread(worker).start();
            }
        }
    }
}

锁成功的运行结果:

posted @ 2020-04-15 02:03  踏步  阅读(1034)  评论(0编辑  收藏  举报