常见的并发模型_两个常见的并发错误
常見的并發(fā)模型
作為Baeldung的編輯,我很高興與一位作者一起撰寫有關(guān)Java通用并發(fā)陷阱的文章。 這是一本不錯(cuò)的書,但是假設(shè)開發(fā)人員具有一定的能力。
我已經(jīng)看到了幾件即時(shí)并發(fā)失敗的事情。 它們很容易添加到代碼中,并保證為您提供奇怪的結(jié)果。 開發(fā)人員仍會(huì)提交這些事實(shí),這是對(duì)我們?nèi)绾螌?duì)OO和并發(fā)進(jìn)行教育的一種評(píng)論,如果使用不當(dāng),這將非常危險(xiǎn)。
除了代碼審查
作為代碼審查員,這些年來我已經(jīng)開發(fā)了一些速記。 這些幫助我發(fā)現(xiàn)了在較大的代碼更改中需要更詳細(xì)地研究的區(qū)域。 它們包括紅旗的事情,我希望出問題。 訓(xùn)練自己去發(fā)現(xiàn)關(guān)鍵的反模式或潛在的反模式是一個(gè)好主意,因?yàn)樗鼈兛梢允怯行У拇a,但會(huì)導(dǎo)致無效的行為。
Bean中的請(qǐng)求狀態(tài)
在Java應(yīng)用程序中,服務(wù),控制器,處理程序和存儲(chǔ)庫(kù)通常是單例的。 它們是在應(yīng)用啟動(dòng)時(shí)創(chuàng)建的,然后請(qǐng)求通常通過多個(gè)線程傳遞給它們。
考慮如下代碼:
public void processOrder(Order order) { ... currentLineItem = order.getLine( 0 ); processLineItem(); } private void processLineItem() { myService.store(currentLineItem); }在這種情況下,該類的作者已決定該對(duì)象可以記住其當(dāng)前正在處理的項(xiàng)目,從而節(jié)省了將該項(xiàng)目傳遞給下一個(gè)函數(shù)的工作。
這違反了兩個(gè)原則:線程安全和有意義的對(duì)象狀態(tài)。 訂單處理者不太可能真正了解其正在處理的訂單。 您可能會(huì)想像一些有狀態(tài)地遍歷某個(gè)訂單,某種游標(biāo),閱讀器或構(gòu)建器的項(xiàng)目,但是將所有這些項(xiàng)目混合到一個(gè)對(duì)象中卻是很泥濘的。
不過,最重要的是,有一個(gè)明確的定義可以解釋為什么這是錯(cuò)誤的。 如果將請(qǐng)求的每個(gè)屬性放入該請(qǐng)求的接收者中,那么您將有兩個(gè)風(fēng)險(xiǎn):
- 在多線程執(zhí)行中的請(qǐng)求之間出血
- 如果事情沒有完全整理,則在單線程的請(qǐng)求之間流血
簡(jiǎn)而言之,永不做!
瘋狂的懶惰初始化
延遲初始化允許:
- 由于以下原因,啟動(dòng)速度更快
- 必要時(shí)及時(shí)加載資源
- 如果不需要,則不加載資源(例如,無服務(wù)器Lambda,在其生命周期中可能永遠(yuǎn)不會(huì)被要求執(zhí)行特定的代碼路徑)
- 定制如何通過較早發(fā)生的活動(dòng)加載資源
所有這些都很好。 但是,此代碼:
private LazyService getLazyService() { if (lazyService != null ) { return lazyService; } LazyService newLazyService = connectToLazyService(); registerWithServiceRegistry(newLazyService); lazyService = newLazyService; return newLazyService; }盡管它可以工作,但可以同時(shí)調(diào)用并出錯(cuò)。 它的錯(cuò)誤程度取決于各種各樣的事情。 在示例中,我試圖暗示我們正在處理的事情:
- 在并發(fā)調(diào)用中,發(fā)生了多個(gè)延遲加載…
- ……如果這很昂貴,那是浪費(fèi)
- 如果發(fā)生多個(gè)懶惰加載,則可能兩個(gè)對(duì)象在內(nèi)存中的駐留時(shí)間超過了所需時(shí)間,或者永遠(yuǎn)存在
- 如果這是單例,則獲取孤立對(duì)象的請(qǐng)求可能無法與其余請(qǐng)求進(jìn)行協(xié)調(diào)
- 使用手工進(jìn)行的非線程安全的對(duì)象初始化真是遺憾
為了正確進(jìn)行單例初始化,您應(yīng)該使用雙重檢查鎖定或使用框架,甚至明智地使用基于static字段的簡(jiǎn)單Java單例。
其他并發(fā)失敗
上面兩個(gè)似乎是最常見的錯(cuò)誤,以至于顯而易見。 如果發(fā)現(xiàn)另一個(gè),請(qǐng)將其放在評(píng)論中。
翻譯自: https://www.javacodegeeks.com/2020/01/two-common-concurrency-bugs.html
常見的并發(fā)模型
總結(jié)
以上是生活随笔為你收集整理的常见的并发模型_两个常见的并发错误的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux动态库加载原理(linux链接
- 下一篇: jpa embedded_JPA @Em