1. 程式人生 > >內建鎖(隱式鎖)和顯示鎖

內建鎖(隱式鎖)和顯示鎖

1.內建鎖:
(1)原理:通過內部的一個叫做監視器鎖的原理來實現的,但是監視器鎖本質又是依賴於底層的作業系統的Mutes Lock來實現的,作業系統之間實現執行緒的切換需要從使用者態轉換到核心態,這個成本非常高,狀態之間轉換需要很長的時間,所以內建鎖效率較低。

(2)如何加鎖和釋放鎖
鎖物件越小越好
內建鎖獲得鎖和釋放鎖是隱式的,進入synchronized修飾的程式碼塊就獲得鎖,走出就釋放鎖
(3)通訊
wait(),notify()
wait()會立刻釋放當前的鎖,並進入等待狀態,等待到相應的notify並重新獲得鎖過後才能繼續執行;notify()不會立刻釋放鎖,必須要等待notify所線上程執行完synchronized塊中的所有程式碼才會釋放
(4)編碼


模式較為簡單,不必顯式的加鎖釋放鎖
(5)靈活性
一旦進入等待狀態沒既不能中斷也不能取消,容易產生飢餓和死鎖的問題
線上程呼叫notify方法時,會隨機選擇相應的物件的等待佇列的一個執行緒將其喚醒,而不是按照FIFO(先入先出佇列)。
(6)效能
與顯示鎖相效率較低,但是java6以後效能差別不大
2.顯式鎖
參考原文:http://blog.csdn.net/ghsau/article/details/7461369/
在一些內建鎖無法滿足需求的情況下,顯式鎖可以作為一種高階工具。當需要一些高階功能時才應該使用ReentrantLock,這些功能包括:可定時,可輪詢,可中斷,公平佇列,及非塊結構的鎖。否則還是應該優先使用synchronized。
讀寫鎖: ReadWriteLock

class Data {      
    private int data;// 共享資料  
    private ReadWriteLock rwl = new ReentrantReadWriteLock();     
    public void set(int data) {  
        rwl.writeLock().lock();// 取到寫鎖  
        try {  
            System.out.println(Thread.currentThread().getName() + "準備寫入資料");  
            try
{ Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } this.data = data; System.out.println(Thread.currentThread().getName() + "寫入" + this.data); } finally { rwl.writeLock().unlock();// 釋放寫鎖 } } public void get() { rwl.readLock().lock();// 取到讀鎖 try { System.out.println(Thread.currentThread().getName() + "準備讀取資料"); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "讀取" + this.data); } finally { rwl.readLock().unlock();// 釋放讀鎖 } } } public static void main(String[] args) { final Data data = new Data(); for (int i = 0; i < 3; i++) { new Thread(new Runnable() { public void run() { for (int j = 0; j < 5; j++) { data.set(new Random().nextInt(30)); } } }).start(); } for (int i = 0; i < 3; i++) { new Thread(new Runnable() { public void run() { for (int j = 0; j < 5; j++) { data.get(); } } }).start(); } }