Java如何在臨界區(qū)中避免競(jìng)態(tài)條件
當(dāng)兩個(gè)線程競(jìng)爭同一資源時(shí),如果對(duì)資源的訪問順序敏感,就稱存在競(jìng)態(tài)條件。導(dǎo)致競(jìng)態(tài)條件發(fā)生的代碼區(qū)稱作臨界區(qū)。在臨界區(qū)中使用適當(dāng)?shù)耐骄涂梢员苊飧?jìng)態(tài)條件。
界區(qū)實(shí)現(xiàn)方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實(shí)現(xiàn)。synchronized 關(guān)鍵字,代表這個(gè)方法加鎖,相當(dāng)于不管哪一個(gè)線程(例如線程A),運(yùn)行到這個(gè)方法時(shí),都要檢查有沒有其它線程B(或者C、 D等)正在用這個(gè)方法(或者該類的其他同步方法),有的話要等正在使用synchronized方法的線程B(或者C 、D)運(yùn)行完這個(gè)方法后再運(yùn)行此線程A,沒有的話,鎖定調(diào)用者,然后直接運(yùn)行。它包括兩種用法:synchronized 方法和 synchronized 塊。
Java語言的關(guān)鍵字,可用來給對(duì)象和方法或者代碼塊加鎖,當(dāng)它鎖定一個(gè)方法或者一個(gè)代碼塊的時(shí)候,同一時(shí)刻最多只有一個(gè)線程執(zhí)行這段代碼。當(dāng)兩個(gè)并發(fā)線程訪問同一個(gè)對(duì)象object中的這個(gè)加鎖同步代碼塊時(shí),一個(gè)時(shí)間內(nèi)只能有一個(gè)線程得到執(zhí)行。另一個(gè)線程必須等待當(dāng)前線程執(zhí)行完這個(gè)代碼塊以后才能執(zhí)行該代碼塊。然而,當(dāng)一個(gè)線程訪問object的一個(gè)加鎖代碼塊時(shí),另一個(gè)線程仍可以訪問該object中的非加鎖代碼塊。
有臨界區(qū)是為了讓更多的其它線程能安全夠訪問資源。
class Counter { protected long count = 0; public void add(long value) { this.count = this.count + value; } }
觀察線程A和B交錯(cuò)執(zhí)行會(huì)發(fā)生什么,兩個(gè)線程分別加了2和3到count變量上,兩個(gè)線程執(zhí)行結(jié)束后count變量的值應(yīng)該等于5。然而由于兩個(gè)線程是交叉執(zhí)行的,兩個(gè)線程從內(nèi)存中讀出的初始值都是0。然后各自加了2和3,并分別寫回內(nèi)存。最終的值并不是期望的5,而是最后寫回內(nèi)存的那個(gè)線程的值,上面例子中最后寫回內(nèi)存的是線程A,但實(shí)際中也可能是線程B。如果沒有采用合適的同步機(jī)制,線程間的交叉執(zhí)行情況就無法預(yù)料。
add()方法就是一個(gè)臨界區(qū),它會(huì)產(chǎn)生競(jìng)態(tài)條件。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。
相關(guān)文章:
1. ajax請(qǐng)求添加自定義header參數(shù)代碼2. ASP基礎(chǔ)知識(shí)VBScript基本元素講解3. Python requests庫參數(shù)提交的注意事項(xiàng)總結(jié)4. IntelliJ IDEA導(dǎo)入jar包的方法5. Gitlab CI-CD自動(dòng)化部署SpringBoot項(xiàng)目的方法步驟6. Kotlin + Flow 實(shí)現(xiàn)Android 應(yīng)用初始化任務(wù)啟動(dòng)庫7. 利用CSS3新特性創(chuàng)建透明邊框三角8. python爬蟲學(xué)習(xí)筆記之pyquery模塊基本用法詳解9. ASP中解決“對(duì)象關(guān)閉時(shí),不允許操作。”的詭異問題……10. python操作mysql、excel、pdf的示例
