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();
            }
        }
    }
}

鎖成功的運行結果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM