淺談Java併發編程系列(五)—— ReentrantLock VS synchronized

ReentrantLock是Java併發包中一個很是有用的組件,一些併發集合類也是用ReentrantLock實現,包括ConcurrentHashMap。ReentrantLock具備三個特性:等待可中斷、可實現公平鎖、以及鎖能夠綁定多個條件。html

Java中的ReentrantLock

ReentrantLock與synchronized關鍵字同樣,屬於互斥鎖,synchronized中的鎖是非公平的(公平鎖是指多個線程等待同一個鎖時,必須按照申請鎖的時間順序來依次得到鎖),ReentrantLock默認狀況下也是非公平的,但能夠經過帶布爾值的構造函數要求使用公平鎖。線程經過ReentrantLock的lock()方法得到鎖,用unlock()方法釋放鎖。java

ReentrantLock和synchronized關鍵字的區別

  1. ReentrantLock在等待鎖時可使用lockInterruptibly()方法選擇中斷, 改成處理其餘事情,而synchronized關鍵字,線程須要一直等待下去。一樣的,tryLock()方法能夠設置超時時間,用於在超時時間內一直獲取不到鎖時進行中斷。併發

  2. ReentrantLock能夠實現公平鎖,而synchronized的鎖是非公平的。ide

  3. ReentrantLock擁有方便的方法用於獲取正在等待鎖的線程。函數

  4. ReentrantLock能夠同時綁定多個Condition對象,而synchronized中,鎖對象的wait()和notify()或notifyAll()方法能夠實現一個隱含的條件,若是要和多於一個條件關聯時,只能再加一個額外的鎖,而ReentrantLock只須要屢次調用newCondition方法便可。性能

性能比較

在JDK1.6以前,ReentrantLock的性能要明顯優於synchronized,可是JDK1.6中加入了不少針對鎖的優化措施,synchronized和ReentrantLock的性能基本徹底持平了。優化

ReentrantLock缺點

ReentrantLock的主要缺點是方法須要置於try-finally塊中,另外,開發人員須要負責獲取和釋放鎖,而開發人員經常忘記在finally中釋放鎖。線程

ReentrantLock和synchronized示例

import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Java program to show, how to use ReentrantLock in Java.
 * Reentrant lock is an alternative way of locking
 * apart from implicit locking provided by synchronized keyword in Java.
 *
 * @author  Javin Paul
 */
public class ReentrantLockHowto {

    private final ReentrantLock lock = new ReentrantLock();
    private int count = 0;

     //Locking using Lock and ReentrantLock
     public int getCount() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " gets Count: " + count);
            return count++;
        } finally {
            lock.unlock();
        }
     }

     //Implicit locking using synchronized keyword
     public synchronized int getCountTwo() {
            return count++;
     }

    

    public static void main(String args[]) {
        final ThreadTest counter = new ThreadTest();
        Thread t1 = new Thread() {

            @Override
            public void run() {
                while (counter.getCount() < 6) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();                    }
                }
            }
        };
      
        Thread t2 = new Thread() {

            @Override
            public void run() {
                while (counter.getCount() < 6) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                    }
                }
            }
        };
      
        t1.start();
        t2.start();
      
    }
}

Output:
Thread-0 gets Count: 0
Thread-1 gets Count: 1
Thread-1 gets Count: 2
Thread-0 gets Count: 3
Thread-1 gets Count: 4
Thread-0 gets Count: 5
Thread-0 gets Count: 6
Thread-1 gets Count: 7

Read more: http://javarevisited.blogspot...code

相關文章
相關標籤/搜索