摘要:如果沒有采用合適的同步機(jī)制,線程間的交叉執(zhí)行情況就無法預(yù)料。當(dāng)兩個(gè)線程競爭同一資源時(shí),如果對資源的訪問順序敏感,就稱存在競態(tài)條件。導(dǎo)致競態(tài)條件發(fā)生的代碼區(qū)稱作臨界區(qū)。
在同一程序中運(yùn)行多個(gè)線程本身不會(huì)導(dǎo)致問題,問題在于多個(gè)線程訪問了相同的資源。如,同一內(nèi)存區(qū)(變量,數(shù)組,或?qū)ο螅⑾到y(tǒng)(數(shù)據(jù)庫,web services等)或文件。實(shí)際上,這些問題只有在一或多個(gè)線程向這些資源做了寫操作時(shí)才有可能發(fā)生,只要資源沒有發(fā)生變化,多個(gè)線程讀取相同的資源就是安全的。
多線程同時(shí)執(zhí)行下面的代碼可能會(huì)出錯(cuò):
public class Counter { protected long count = 0; public void add(long value){ this.count = this.count + value; } }
想象下線程A和B同時(shí)執(zhí)行同一個(gè)Counter對象的add()方法,我們無法知道操作系統(tǒng)何時(shí)會(huì)在兩個(gè)線程之間切換。JVM并不是將這段代碼視為單條指令來執(zhí)行的,而是按照下面的順序:
從內(nèi)存獲取 this.count 的值放到寄存器
將寄存器中的值增加value
將寄存器中的值寫回內(nèi)存
觀察線程A和B交錯(cuò)執(zhí)行會(huì)發(fā)生什么:
this.count = 0; A: 讀取 this.count 到一個(gè)寄存器 (0) B: 讀取 this.count 到一個(gè)寄存器 (0) B: 將寄存器的值加2 B: 回寫寄存器值(2)到內(nèi)存. this.count 現(xiàn)在等于 2 A: 將寄存器的值加3 A: 回寫寄存器值(3)到內(nèi)存. this.count 現(xiàn)在等于 3
兩個(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ù)料。
當(dāng)兩個(gè)線程競爭同一資源時(shí),如果對資源的訪問順序敏感,就稱存在競態(tài)條件。導(dǎo)致競態(tài)條件發(fā)生的代碼區(qū)稱作臨界區(qū)。上例中add()方法就是一個(gè)臨界區(qū),它會(huì)產(chǎn)生競態(tài)條件。在臨界區(qū)中使用適當(dāng)?shù)耐骄涂梢员苊飧倯B(tài)條件。
原文 Race conditions and critical sections
翻譯 He Jianjun 校對 丁一
via ifeve
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64055.html
摘要:線程需要避免竟態(tài),死鎖以及很多其他共享狀態(tài)的并發(fā)性問題。用戶線程在前臺(tái),守護(hù)線程在后臺(tái)運(yùn)行,為其他前臺(tái)線程提供服務(wù)。當(dāng)所有前臺(tái)線程都退出時(shí),守護(hù)線程就會(huì)退出。線程阻塞等待獲取某個(gè)對象鎖的訪問權(quán)限。 1、多線程介紹 多線程優(yōu)點(diǎn) 資源利用率好 程序設(shè)計(jì)簡單 服務(wù)器響應(yīng)更快 多線程缺點(diǎn) 設(shè)計(jì)更復(fù)雜 上下文切換的開銷 增加資源消耗線程需要內(nèi)存維護(hù)本地的堆棧,同時(shí)需要操作系統(tǒng)資源管理線程。...
摘要:父進(jìn)程調(diào)用創(chuàng)建子進(jìn)程。因而,一個(gè)進(jìn)程的第一個(gè)線程會(huì)隨著這個(gè)進(jìn)程的啟動(dòng)而創(chuàng)建,這個(gè)線程被稱為該進(jìn)程的主線程。另一方面,線程不可能獨(dú)立于進(jìn)程存在。終止線程線程可以通過多種方式來終結(jié)同一個(gè)進(jìn)程中的其他線程。 前言 不積跬步,無以至千里;不積小流,無以成江海。在學(xué)習(xí)Java多線程相關(guān)的知識(shí)前,我們首先需要去了解一點(diǎn)操作系統(tǒng)的進(jìn)程、線程以及相關(guān)的基礎(chǔ)概念。 進(jìn)程 通常,我們把一個(gè)程序的執(zhí)行稱為一...
摘要:并發(fā)需要解決的問題功能性問題線程同步面臨兩個(gè)問題,想象下有兩個(gè)線程在協(xié)作工作完成某項(xiàng)任務(wù)。鎖可用于規(guī)定一個(gè)臨界區(qū),同一時(shí)間臨界區(qū)內(nèi)僅能由一個(gè)線程訪問。并發(fā)的數(shù)據(jù)結(jié)構(gòu)線程安全的容器,如等。 并發(fā)指在宏觀上的同一時(shí)間內(nèi)同時(shí)執(zhí)行多個(gè)任務(wù)。為了滿足這一需求,現(xiàn)代的操作系統(tǒng)都抽象出 線程 的概念,供上層應(yīng)用使用。 這篇博文不打算詳細(xì)展開分析,而是對java并發(fā)中的概念和工具做一個(gè)梳理。沿著并發(fā)模...
閱讀 1611·2021-11-22 09:34
閱讀 1695·2019-08-29 16:36
閱讀 2676·2019-08-29 15:43
閱讀 3119·2019-08-29 13:57
閱讀 1305·2019-08-28 18:05
閱讀 1881·2019-08-26 18:26
閱讀 3251·2019-08-26 10:39
閱讀 3466·2019-08-23 18:40