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.導(dǎo)致拋出ConcurrentModificationException異常的原因?
首先袍榆,對容器類進行迭代的標準方式就是使用Iterator肉微,但在設(shè)計同步容器類的迭代器時并沒有考慮到并發(fā)修改的問題,并且它們表現(xiàn)出的行為是”及時失敗“(fail-fast)的蜡塌。這就意味著碉纳,當它們發(fā)現(xiàn)容器在迭代過程中被修改時,就會拋出一個ConcurrentModificationException異常馏艾。
其次劳曹,這種”及時失敗“的迭代器并不是一種完備的處理機制,只是”善意地“捕獲并發(fā)錯誤琅摩,因此只能作為并發(fā)問題的預(yù)警指示器铁孵。
最后,如果不希望在迭代期間對容器加鎖房资,那么一種替代的方式就是”克隆“容器蜕劝,并在副本上進行迭代。
3.經(jīng)典并發(fā)容器類的介紹
通過并發(fā)容器來代替同步容器,可以極大地提高伸縮性并降低風(fēng)險岖沛。
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.雙端隊列與工作密戎恕(work stealing)
在工作密取的設(shè)計中,每個消費者都有自己的雙端隊列庄岖。如果一個消費者完成自己雙端隊列中的全部工作豁翎,那么它可以從其他的消費者雙端隊列秘密獲取工作。
優(yōu)勢:比傳統(tǒng)的生產(chǎn)者-消費者模式具有更高的伸縮性隅忿,減少競爭的發(fā)生心剥。
6.阻塞產(chǎn)生的原因?中斷異常出現(xiàn)的處理方式背桐?
導(dǎo)致線程阻塞的原因包括:等待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)建緩存的學(xué)習(xí)扭吁?
為什么要使用緩存撞蜂?
? ? 緩沖可以縮短響應(yīng)時間,減少不必要的重復(fù)操作侥袜。
設(shè)計緩沖的幾點注意事項蝌诡?
? ? ?是否是線程安全的,是否是原子操作枫吧。
? ? ?有沒有緩存污染的情況浦旱,對于失敗的緩存能否有效的清除。