java的兩種同步方式, Synchronized與ReentrantLock的區別

ava在編寫多線程程序時,爲了保證線程安全,須要對數據同步,常常用到兩種同步方式就是Synchronized和重入鎖ReentrantLock。java

類似點:安全

       這兩種同步方式有不少類似之處,它們都是加鎖方式同步,並且都是阻塞式的同步,也就是說當若是一個線程得到了對象鎖,進入了同步塊,其餘訪問該同步塊的線程都必須阻塞在同步塊外面等待,而進行線程阻塞和喚醒的代價是比較高的(操做系統須要在用戶態與內核態之間來回切換,代價很高,不過能夠經過對鎖優化進行改善)。多線程

區別:jvm

      這兩種方式最大區別就是對於Synchronized來講,它是java語言的關鍵字,是原生語法層面的互斥,須要jvm實現。而ReentrantLock它是JDK 1.5以後提供的API層面的互斥鎖,須要lock()和unlock()方法配合try/finally語句塊來完成。ide

1.Synchronized函數

    Synchronized進過編譯,會在同步塊的先後分別造成monitorenter和monitorexit這個兩個字節碼指令。在執行monitorenter指令時,首先要嘗試獲取對象鎖。若是這個對象沒被鎖定,或者當前線程已經擁有了那個對象鎖,把鎖的計算器加1,相應的,在執行monitorexit指令時會將鎖計算器就減1,當計算器爲0時,鎖就被釋放了。若是獲取對象鎖失敗,那當前線程就要阻塞,直到對象鎖被另外一個線程釋放爲止。性能

    public class SynDemo{
     
        public static void main(String[] arg){
            Runnable t1=new MyThread();
            new Thread(t1,"t1").start();
            new Thread(t1,"t2").start();
        }
     
    }
    class MyThread implements Runnable {
     
        @Override
        public void run() {
            synchronized (this) {
                for(int i=0;i<10;i++)
                    System.out.println(Thread.currentThread().getName()+":"+i);
            }
            
        }
     
    }優化

查看字節碼指令:this

2.ReentrantLock操作系統

   因爲ReentrantLock是java.util.concurrent包下提供的一套互斥鎖,相比Synchronized,ReentrantLock類提供了一些高級功能,主要有如下3項:

        1.等待可中斷,持有鎖的線程長期不釋放的時候,正在等待的線程能夠選擇放棄等待,這至關於Synchronized來講能夠避免出現死鎖的狀況。

        2.公平鎖,多個線程等待同一個鎖時,必須按照申請鎖的時間順序得到鎖,Synchronized鎖非公平鎖,ReentrantLock默認的構造函數是建立的非公平鎖,能夠經過參數true設爲公平鎖,但公平鎖表現的性能不是很好。

        3.鎖綁定多個條件,一個ReentrantLock對象能夠同時綁定對個對象。

ReentrantLock的用法以下:

    public class SynDemo{               public static void main(String[] arg){             Runnable t1=new MyThread();             new Thread(t1,"t1").start();             new Thread(t1,"t2").start();         }           }     class MyThread implements Runnable {               private Lock lock=new ReentrantLock();         public void run() {                 lock.lock();                 try{                     for(int i=0;i<5;i++)                         System.out.println(Thread.currentThread().getName()+":"+i);                 }finally{                     lock.unlock();                 }         }           }  

相關文章
相關標籤/搜索