synchronized和java.util.concurrent.locks.Lock的异同
主要相同点:
Lock能完成synchronized所实现的所有功能,在synchronized中隱含著物件鎖定與釋放鎖定的觀念
主要不同点:
Lock有比synchronized更精确的线程语义和更好的性能 synchronized会自动释放锁.而Lock一定要求程序员手工释放.并且必须在finally从句
中释放
Lock 與 Condition
對於初學者來說,執行緒的同步化 並非是個容易理解的議題,在synchronized中隱含著物件鎖定與釋放鎖定的觀念,程式中並沒有明顯的語意來告知這一點,而必須靠程式設計人員本身記憶物件的鎖定與釋放鎖定問題。
在java.util.concurrent.locks套件中新增了Lock與Condition等類別,可以讓您明確的在程式中進行明確的鎖定與釋放鎖定。
Lock是一個介面,其中規範了lock()、unclock()與newCondition()三種方法:
lock() 用來取得物件的鎖定。
unlock() 用來釋放物件的鎖定,通常由同一個Lock物件來呼叫lock()與unlock()。
newCondition() 建立一個與Lock物件相關聯的Conditon物件。
Condition是一個介面,作用是在執行緒之間進行溝通,就如其名稱所示,告知執行緒目前的狀況為何,是要等待?還是通知?其規範的幾個重要方法為:await() 告知目前的執行緒等待,直到被通知或中斷(interrupted)。
signal() 通知目前等待中的一個執行緒,從上次的等待點繼續執行,類似物件的notify()方法
signalAll() 通知目前等待中的所有執行緒參與鎖定競爭,而後從上次的等待點繼續執行,類似物件的notifyAll()方法。
在這邊直接改寫wait ()、notify() 中的Clerk類別,不使用synchronized、wait()、notify(),而改用Lock與Condition,其中ReentrantLock為Lock介面的一個實作類別:
Clerk.java
import java.util.concurrent.locks.*;
public class Clerk {
private Lock lock = new ReentrantLock();
private Condition threadCond = lock.newCondition();
// -1 表示目前沒有產品
private int product = -1;
// 這個方法由生產者呼叫
public void setProduct(int product) {
lock.lock();
try {
if(this.product != -1) {
try {
// 目前店員沒有空間收產品,請稍候!
threadCond.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
this.product = product;
System.out.printf("生產者設定 (%d)%n", this.product);
// 通知等待區中的一個消費者可以繼續工作了
threadCond.signal();
}
finally {
lock.unlock();
}
}
// 這個方法由消費者呼叫
public int getProduct() {
lock.lock();
int p = 0;
try {
if(this.product == -1) {
try {
// 缺貨了,請稍候!
threadCond.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
p = this.product;
System.out.printf(
"消費者取走 (%d)%n", this.product);
this.product = -1;
// 通知等待區中的一個生產者可以繼續工作了
threadCond.signal();
}
finally {
lock.unlock();
}
return p;
}
}
本文对比了synchronized和Lock的异同,详细介绍了Lock及其Condition接口如何提供更精细的线程控制和更好的性能。通过实例展示了如何使用ReentrantLock及Condition进行线程间的同步。
10万+

被折叠的 条评论
为什么被折叠?



