synchronized雙重校驗問題


  今天寫synchronized用例的時候,兩個線程共享一個對象數據,當操作i的時候,在同步代碼塊外面判斷了一次i<100,但是每一次跑,都會出現i=100,的情況。此時我想起了單例模式的雙重校驗鎖,為什么要判斷兩次呢?因為可能出現線程1和線程2,在i=99的時候,同時判斷了一次,都進到了for循環里面,此時線程1進入同步代碼塊,線程2進如阻塞隊列。當線程1時間片用完,但是代碼塊並沒有執行完。此時,線程2也滿足if條件進入同步代碼塊,之后就會出現線程1和線程2都對i進行了加1,就輸出i = 100(同理·,如果三個線程則可能出現101的情況),所以要在同步代碼塊中再加一次判斷,判斷i的值

  synchronized代碼塊使用起來比synchronized方法要靈活得多。因為也許一個方法中只有一部分代碼只需要同步,如果此時對整個方法用synchronized進行同步,會影響程序執行效率。而使用synchronized代碼塊就可以避免這個問題,synchronized代碼塊可以實現只對需要同步的地方進行同步

import java.util.ArrayList;

/**
 * @Classname DoubleChecking
 * @Description TODO
 * @Date 2020/7/21 13:20
 * @Created by Fearless
 */
public class DoubleChecking {
    public class Data{
        private ArrayList<Integer> arr = new ArrayList<>();
        private Integer i ;
        public void insert(){
            for (i = 0 ; i < 100 ; ++i){
                synchronized (this){
                    //再次校驗避免阻塞線程改變i值
                    if (i < 100){
                        if (!arr.contains(i)){
                            arr.add(i);
                            System.out.println(Thread.currentThread().getName()+"正在插入"+i);
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        DoubleChecking doubleChecking = new DoubleChecking();
        Data data = doubleChecking.new Data();
        new Thread(() -> data.insert(),"t1").start();
        new Thread(() -> data.insert(),"t2").start();
        Thread.sleep(3000);
    }
}

 


免責聲明!

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



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