synchronized 與 Lock區別

在上一篇文章中,我們談到了採用synchronized來實現多線程同步,在Java中還一種實現多線程同步的方法,那就是Lock。下面主要談談這兩種多線程同步的區別。
1、synchronized是在JVM層面實現的,系統可以監控鎖的釋放與否。
2、ReentrantLock使用代碼實現的,系統無法自動釋放鎖,需要在代碼中finally子句中顯式釋放鎖lock.unlock()。
3、相對於synchronized,ReentrantLock還多了 鎖投票,定時鎖等候和中斷鎖等候。
例:線程A和B都要獲取對象O的鎖定,假設A獲取了對象O鎖,B將等待A釋放對O的鎖定,
如果使用 synchronized ,如果A不釋放,B將一直等下去,不能被中斷
如果 使用ReentrantLock,如果A不釋放,可以使B在等待了足夠長的時間以後,中斷等待,而幹別的事情。
4、synchronized是由系統監控,對於業務不是很熟悉的開發者來說,用起來更省心,但是在併發量比較高的情況下,其性能下降很嚴重,此時ReentrantLock是個不錯的方案。

用Lock實現同步例子:

public class Consumer implements Runnable {

     private Lock lock;
     public Consumer(Lock lock) {
            this. lock = lock;
     }
     @Override
     public void run() {
            // TODO Auto-generated method stub
            int count = 10;
            while( count > 0 ) {
                 try {
                      lock.lock();
                     count --;
                     System. out.print( "B");
                } finally {
                      lock.unlock(); //主動釋放鎖
                      try {
                           Thread. sleep(91L);
                     } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                           e.printStackTrace();
                     }
                }
           }

     }

}

public class Producer implements Runnable{

     private Lock lock;
     public Producer(Lock lock) {
            this. lock = lock;
     }
     @Override
     public void run() {
            // TODO Auto-generated method stub
            int count = 10;
            while (count > 0) {
                 try {
                      lock.lock();
                     count --;
                     System. out.print( "A");
                } finally {
                      lock.unlock();
                      try {
                           Thread. sleep(90L);
                     } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                           e.printStackTrace();
                     }
                }
           }
     }
}

調用代碼:

public class Test {

     public static void main(String[] args) {
           Lock lock = new ReentrantLock();

           Consumer consumer = new Consumer(lock);
           Producer producer = new Producer(lock);

            new Thread(consumer).start();
            new Thread( producer).start();

     }
}

忠告:多線程同步的時候,優先考慮synchronized,如果有特殊需要,再進一步優化。ReentrantLock和Atomic如果用的不好,不僅不能提高性能,還可能帶來災難。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章