同步容器、并發(fā)容器及使用

1.什么是同步容器?同步容器使用什么方式實現(xiàn)線程安全

同步容器可以簡單的理解位通過synchronized來實現(xiàn)同步的容器,如果有多個線程調(diào)用同步容器的方法,它們將會串行執(zhí)行。包括Vector和Hashtable,以及由同步容器封裝類。Collections.synchronizedXxx等工廠方法創(chuàng)建的類。

同步容器實現(xiàn)線程安全的方式將它們的狀態(tài)封裝起來,并對每個公有方法同步,使得每次只有一個線程能夠訪問容器的狀態(tài)。

注意通過在迭代期間持有Vector的鎖,可以防止其他線程在迭代期間修改Vector,但也因此降低了并發(fā)性。

2.導致拋出ConcurrentModificationException異常的原因?

首先,對容器類進行迭代的標準方式就是使用Iterator,但在設(shè)計同步容器類的迭代器時并沒有考慮到并發(fā)修改的問題,并且它們表現(xiàn)出的行為是”及時失敗“(fail-fast)的。這就意味著,當它們發(fā)現(xiàn)容器在迭代過程中被修改時,就會拋出一個ConcurrentModificationException異常。

其次,這種”及時失敗“的迭代器并不是一種完備的處理機制,只是”善意地“捕獲并發(fā)錯誤,因此只能作為并發(fā)問題的預(yù)警指示器。

最后,如果不希望在迭代期間對容器加鎖,那么一種替代的方式就是”克隆“容器,并在副本上進行迭代。

3.經(jīng)典并發(fā)容器類的介紹

通過并發(fā)容器來代替同步容器,可以極大地提高伸縮性并降低風險。

ConcurrentHashMap:基于散列的Map,并不是將每個方法都在同一個鎖上同步使得每次只能有一個線程訪問線程,而使用一種更細粒度的加鎖機制來實現(xiàn)更大程度的共享。這種機制稱為分段鎖(Lock Striping)。在這種機制中,任意數(shù)量的讀取線程可以并發(fā)地訪問map,執(zhí)行讀取操作的線程和執(zhí)行寫入操作的線程可以并發(fā)地訪問map,并且一定數(shù)量的寫入線程可以并發(fā)地修改map。ConcurrentHashMap帶來的結(jié)果是,在并發(fā)訪問的環(huán)境下將實現(xiàn)更高的吞吐量,而在單線程環(huán)境中只損失非常小的性能。

ConcurrentHashMap與其他并發(fā)容器一起增強了同步容器類:它們提供的迭代器不會拋出ConcurrentModificationException,因此不需要在迭代過程中對容器加鎖。ConcurrentHashMap返回的迭代器具有弱一致性。弱一致性的迭代器可以容忍并發(fā)的修改,當創(chuàng)建迭代器時會遍歷已有的元素,并可以(但是不保證)在迭代器被構(gòu)造后將修改操作反應(yīng)給容器。

CopyOnWriteArrayList用于替代同步List,在迭代期間不需要對容器進行加鎖或復(fù)制。“寫入時復(fù)制(Copy-On-Write)”容器的線程安全性在于,只要是正確發(fā)布一個事實不可變的對象,那么在訪問該對象時就不再需要進一步的同步。在每次修改時,都會創(chuàng)建并重新發(fā)布一個新的容器副本,從而實現(xiàn)可變性。

注意:僅當?shù)牟僮鬟h遠多于修改操作時,才應(yīng)該使用“寫入時復(fù)制“的容器。

4.阻塞隊列和生產(chǎn)者-消費者模式

阻塞隊列分為有界隊列和無界隊列,支持阻塞的put、take和定時的offer和poll方法。常見的生產(chǎn)者-消費者設(shè)計模式就是線程池和工作隊列的組合。

offer方法:如果數(shù)據(jù)項不能夠被添加到隊列中,那么將返回一個失敗的狀態(tài)而不是阻塞直至可以添加。這個方法的使用可以提供更靈活的方式來處理負載過荷的情況,例如減輕負載,將多余的工作項序列化并寫入磁盤,減少生產(chǎn)者的數(shù)量,或者通過某種方式來抑制生產(chǎn)者線程。

5.雙端隊列與工作密?。╳ork stealing)

在工作密取的設(shè)計中,每個消費者都有自己的雙端隊列。如果一個消費者完成自己雙端隊列中的全部工作,那么它可以從其他的消費者雙端隊列秘密獲取工作。

優(yōu)勢:比傳統(tǒng)的生產(chǎn)者-消費者模式具有更高的伸縮性,減少競爭的發(fā)生。

6.阻塞產(chǎn)生的原因?中斷異常出現(xiàn)的處理方式?

導致線程阻塞的原因包括:等待I/O操作結(jié)束,等待獲取一個鎖,等待從一個阻塞的方法中醒過來(thread.sleep),或者等待另一個線程的計算機結(jié)果。

當代碼調(diào)用中拋出一個InterruptedException異常的方法時,基本有兩種主要選擇方案:

傳遞InterruptedException。將異常的處理權(quán)傳遞給方法的調(diào)用者(可以捕獲異常,然后執(zhí)行某種清理的操作再傳遞給上層)。

恢復(fù)中斷。

屏蔽中斷:即對Thread進行擴展,并且控制調(diào)用棧上所有更高層次的代碼。

7.同步工具類

同步工具類包含一些特定的結(jié)構(gòu)化屬性:它們封裝了一些狀態(tài),這些狀態(tài)將決定執(zhí)行同步工具類的線程是繼續(xù)執(zhí)行還是等待。包括信號量(Semaphore)、柵欄(Barrier)、以及閉鎖(Latch)。

閉鎖

? 閉鎖可以用來確保某些活動直到其他活動都完成后才繼續(xù)執(zhí)行。當閉鎖到達結(jié)束狀態(tài)后,將不會再改變狀態(tài)。

? 啟動門將使主線程能夠同時釋放所有工作線程,而結(jié)束們則是主線程能夠等待最后一個線程執(zhí)行完成,而不是順序地等待每個線程執(zhí)行完成。

?注意: FutureTask也可以用作閉鎖,并且可以處于三種狀態(tài):等待運行、正在運行和運行完成。

信號量

? 計數(shù)信號量用來控制同時訪問某個特定資源的操作數(shù)量,或者同時執(zhí)行某個指定操作的數(shù)量。計數(shù)信號量還可以用來實現(xiàn)某種資源池,或者對容器施加邊界。

?注意: 計數(shù)信號量的特殊情況二值信號量,即初始值為1的semaphore,二值信號量可以用作互斥體,并且具備不可重入的加鎖語義:誰擁有這個唯一的許可,誰就擁有了互斥體。

柵欄

柵欄類似于閉鎖,它能阻塞一組線程直到某個事情發(fā)生。柵欄與閉鎖的關(guān)鍵區(qū)別在于,所有線程必須同時到達柵欄的位置,才能繼續(xù)執(zhí)行。閉鎖用于等待事情,而柵欄用于等待其他線程。柵欄可被重用。

8.如何構(gòu)建緩存的學習?

為什么要使用緩存?

? ? 緩沖可以縮短響應(yīng)時間,減少不必要的重復(fù)操作。

設(shè)計緩沖的幾點注意事項?

? ? ?是否是線程安全的,是否是原子操作。

? ? ?有沒有緩存污染的情況,對于失敗的緩存能否有效的清除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容