實戰Java高併發程式設計(三)JDK並發包

2021-08-04 07:29:07 字數 2946 閱讀 3061

同步控制——重入鎖

重入鎖可以完全替代synchronized關鍵字。其使用方法如下:

public reentrantlock lock = new reentrantlock();

public void run()finally

}

由於其通過人工進行lock和unlock,因此比synchronized更好控制臨界區。

注意,這段**有兩個lock.lock();,這也是為啥這叫衝入鎖的原因,同乙個執行緒可以多次獲得鎖,但是必須要多次釋放該鎖,否則其它執行緒無法進入該臨界區。

在重入鎖的實現中,主要包含三個要素:

第一是原子狀態。原子狀態使用cas操作來儲存當前鎖的狀態,判斷鎖是已經被被的執行緒持有。

第二是等待佇列。所有沒有請求到鎖的執行緒,會進入等待佇列進行等待。待有執行緒釋放鎖後,系統就能從等待隊裡中喚醒乙個執行緒,繼續工作。

第三是阻塞原語park()和unpark(),用來掛起和恢復執行緒。沒有得到鎖的執行緒將會被掛起。

condition條件

wait()和notify()方法是和synchronized關鍵字合作使用的,而condition的await()和signal()是與重入鎖相關聯的。

當執行緒使用condition.await()時,要求執行緒持有相關的重入鎖,在condition.await()呼叫後,這個執行緒會釋放這把鎖。同理,在condition.signal()方法呼叫時,也要求執行緒先獲得相關的鎖。在signal()方法呼叫後,系統會從當前condition物件的等待佇列中,喚醒乙個執行緒。一旦執行緒被喚醒,它會重新嘗試獲得與之繫結的重入鎖,一旦成功獲取,就可以繼續執行了。因此,在signal()方法呼叫之後,還需要釋放先關的鎖

public reentrantlock lock = new reentrantlock();

public condition condition = lock.newcondition();

訊號量(semaphore)

訊號量是對鎖的擴充套件,它能夠制定多個執行緒同時訪問某乙個執行緒。申請訊號量是用acquire()操作,離開臨界區時,務必要使用release()釋放訊號量,否則會導致能進入臨界區的執行緒越來越少,最後所有的執行緒均不可訪問臨界區。

讀寫鎖(readwritelock)

在乙個系統中,讀-讀不互斥、讀-寫互斥、寫-寫互斥,在讀操作消耗遠高於寫消耗的情況下,讀寫分離能夠有效地減少鎖競爭,提公升系統效能。我們可以通過以下方法來獲得讀鎖(readlock)和寫鎖(writelock)。

private static reentrantreadwritelock readwritelock = new reentrantreadwritelock();

private static lock readlock = readwritelock.readlock();//獲得讀鎖

private static lock writelock = readwritelock.writelock();//獲得寫鎖

計數器(countdownlatch)

這個工具通常用來控制線程等待,它可以讓某乙個執行緒等待,直到計數結束再執行。比如有4個執行緒跑4個任務a、b、c、d,d任務需要abc都完成之後才能執行,此時就能夠使用countdownlatch。一下例子輸出4中模擬讀寫鎖的總耗時。

public

class test

catch (interruptedexception e) finally

}public

void

write(lock lock,int val)finally

}public

static

void

main(string args) throws interruptedexception ;

runnable writerunnable = ()->;

long beg = new date().gettime();

for(int i = 0 ;i<20;i++)

for(int j = 0 ; j< 20 ;j++)

latch.await();//如果計數器沒到0,則阻塞;當計數器到0時,則繼續執行。

system.out.println(system.currenttimemillis()-beg);

}}

迴圈柵欄(cyclicbarrier)

cyclicbarrier是countdownlatch的加強版,它能夠迴圈計數,每次計數完成之後,會執行指定的方法。其建構函式如下:

public cyclicbarrier(int parties, runnable barrieraction)

其中parties用來指定執行緒數量,barrieraction用來指定每次計數完成之後,執行的函式。注意:這個函式由這輪計數,最後乙個到來的執行緒執行。

> locksupport.park()方法可以阻塞當前執行緒

> locksupport.parknanos(long nanos)能夠實現乙個限時等待。

> locksupport.parkuntil(long deadline)能夠指定等待的最晚時間。

locksupport使用了類似訊號量的機制,它為每乙個執行緒準備了乙個許可,如果許可可用,那麼park()方法就會立刻返回,否則就會阻塞。而unpark()方法則使得乙個許可變為可用。

執行緒池

與程序相比,執行緒是一種輕量級的工具,但是其建立和關閉依然會花費時間。並且大量的執行緒會搶占記憶體資源,也會給gc帶來很大壓力。因此在實際專案中,執行緒的數量必須加以控制,盲目地建立執行緒可能會降低系統效能。

JDK同步控制工具,JAVA高併發程式設計

同步控制是併發程式的重要手段之一,我們平常用過最多的synchronized就是其中一種簡單的方法,此外還有object.wait object.notify 等方法。在jdk之中,還有其他好用的工具。乙個可重入的互斥鎖lock,它具有與使用synchronized方法和語句所訪問的隱式監視器鎖相同...

實戰Java高併發程式設計之概念

學習高併發你必須知道的幾個重要的概念 1.同步 synchronous 和非同步 asynchronous 同步和非同步是對方法的呼叫而言的 同步呼叫時,會等待呼叫的方法完成以後才能繼續執行這個方法。非同步呼叫的時候會瞬間的返回,但是並不是表示這個請求已經完成了,但是會在後台起乙個執行緒去執行接下來...

Java的高併發程式設計系列(三)

鎖定某物件o,如果o的屬性發生改變,不影響鎖的使用,但是如果o變成另外乙個物件,則鎖定的物件發生改變,應該避免將鎖定物件的引用變成另外乙個物件。public class demo17 catch interruptedexception e system.out.println thread.cur...