大家好,我是LinuxZn。
本次分享線(xiàn)程安全的基礎(chǔ)知識(shí)。
線(xiàn)程安全
在多線(xiàn)程編程中,線(xiàn)程安全是必須要考慮的因素。
什么是線(xiàn)程安全?
在多線(xiàn)程環(huán)境中,多個(gè)線(xiàn)程在同一時(shí)刻對(duì)同一份資源進(jìn)行寫(xiě)操作時(shí),不會(huì)出現(xiàn)數(shù)據(jù)不一致。反之,則是線(xiàn)程非安全的。
線(xiàn)程安全是程序設(shè)計(jì)中的術(shù)語(yǔ),指某個(gè)函數(shù)、函數(shù)庫(kù)在多線(xiàn)程環(huán)境中被調(diào)用時(shí),能夠正確地處理多個(gè)線(xiàn)程之間的公用變量,使程序功能正確完成。
為了確保在多線(xiàn)程環(huán)境中的線(xiàn)程安全,就要確保數(shù)據(jù)的一致性。確保線(xiàn)程安全的幾種方法:
使用互斥鎖
一個(gè)線(xiàn)程,如果需要訪(fǎng)問(wèn)公共資源,需要獲得互斥鎖并對(duì)其加鎖,資源在在鎖定過(guò)程中,如果其它線(xiàn)程對(duì)其進(jìn)行訪(fǎng)問(wèn),也需要獲得互斥鎖,如果獲取不到,線(xiàn)程只能進(jìn)行阻塞,直到獲得該鎖的線(xiàn)程解鎖。關(guān)于互斥鎖的使用:Hello系列 | 多線(xiàn)程編程基礎(chǔ)!
例子(來(lái)源:維基百科):
#includeintincrement_counter(void) { staticintcounter=0; staticpthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&mutex); //onlyallowonethreadtoincrementatatime ++counter; //storevaluebeforeanyotherthreadsincrementitfurther intresult=counter; pthread_mutex_unlock(&mutex); returnresult; }
這個(gè)函數(shù)是線(xiàn)程安全的,可以在多個(gè)線(xiàn)程中被調(diào)用。
使用原子操作
上面的例子中,使用一個(gè) 互斥鎖來(lái)保護(hù)一次簡(jiǎn)單的增量操作顯然過(guò)于昂貴,我們可以使用一些專(zhuān)門(mén)的原子操作API函數(shù)來(lái)替代。如上述例子,c++11中的原子變量提供了一個(gè)可使此函數(shù)既線(xiàn)程安全又可重入(而且還更簡(jiǎn)潔)的替代方案:
#includeintincrement_counter(void) { staticstd::atomic counter(0); //incrementisguaranteedtobedoneatomically intresult=++counter; returnresult; }
Linux內(nèi)核中原子整形操作:
#includeintincrement_counter(void) { atomic_tcounter=ATOMIC_INIT(0); //incrementisguaranteedtobedoneatomically atomic_inc(&counter); intresult=counter; returnresult; }
什么是原子操作?
從字面上簡(jiǎn)單理解,原子是一種很微小的粒子;原子操作是不能再進(jìn)一步細(xì)分的操作。
從上面互斥鎖的例子來(lái)看,在線(xiàn)程層面,線(xiàn)程1和線(xiàn)程2同時(shí)調(diào)用了increment_counter函數(shù),被 mutex 保護(hù)的操作是原子操作,lock、unlock及保護(hù)部分要整體順序運(yùn)行,不可再進(jìn)一步細(xì)分,作為一個(gè)原子存在 。
如果確定某個(gè)操作是原子的,并且有原子操作API函數(shù)可以使用,就不用為了去保護(hù)這個(gè)操作而加上會(huì)耗費(fèi)昂貴性能開(kāi)銷(xiāo)的鎖。
如,Linux內(nèi)核原子整形操作 API 函數(shù)表(來(lái)源:正點(diǎn)原子) :
防止過(guò)度優(yōu)化
線(xiàn)程安全的函數(shù)應(yīng)該為每個(gè)調(diào)用它的線(xiàn)程分配專(zhuān)門(mén)的空間,把多個(gè)線(xiàn)程共享的變量正確對(duì)待(如,通知編譯器該變量為“易失(volatile)”型,阻止其進(jìn)行一些不恰當(dāng)?shù)膬?yōu)化)。
線(xiàn)程安全函數(shù)與可重入函數(shù)?
先明確概念:
線(xiàn)程安全函數(shù):能夠正確地處理多個(gè)線(xiàn)程之間的公用變量的函數(shù)。、
可重入函數(shù):在任意時(shí)刻被中斷然后操作系統(tǒng)調(diào)度執(zhí)行另一段代碼,這段代碼又使用了該副程序不會(huì)出錯(cuò)。
可重入函數(shù)應(yīng)當(dāng)滿(mǎn)足條件:
不能含有靜態(tài)(全局)非常量數(shù)據(jù)。
不能返回靜態(tài)(全局)非常量數(shù)據(jù)的地址。
只能處理由調(diào)用者提供的數(shù)據(jù)。
不能依賴(lài)于單例模式資源的鎖。
調(diào)用(call)的函數(shù)也必需是可重入的。
可重入函數(shù)未必是線(xiàn)程安全的;線(xiàn)程安全函數(shù)未必是可重入的。
例子1:上述例子中的increment_counter函數(shù)是線(xiàn)程安全的,但是并不是可重入的。因?yàn)槭褂昧嘶コ怄i,如果這個(gè)函數(shù)用在可重入的中斷處理程序中,如果在pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)之間產(chǎn)生另一個(gè)調(diào)用函數(shù)increment_counter的中斷,則會(huì)第二次執(zhí)行此函數(shù),此時(shí)由于mutex已被lock,函數(shù)會(huì)在pthread_mutex_lock(&mutex)處阻塞,并且由于mutex沒(méi)有機(jī)會(huì)被unlock,阻塞會(huì)永遠(yuǎn)持續(xù)下去。
例子2:一個(gè)函數(shù)打開(kāi)某個(gè)文件并讀入數(shù)據(jù)。這個(gè)函數(shù)是可重入的,因?yàn)樗亩鄠€(gè)實(shí)例同時(shí)執(zhí)行不會(huì)造成沖突;但它不是線(xiàn)程安全的,因?yàn)樵谒x入文件時(shí)可能有別的線(xiàn)程正在修改該文件,為了線(xiàn)程安全必須對(duì)文件加“同步鎖”。
-
編程
+關(guān)注
關(guān)注
88文章
3639瀏覽量
94026 -
中斷
+關(guān)注
關(guān)注
5文章
900瀏覽量
41791 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4346瀏覽量
63006 -
C++
+關(guān)注
關(guān)注
22文章
2114瀏覽量
73882 -
線(xiàn)程安全
+關(guān)注
關(guān)注
0文章
13瀏覽量
2480
原文標(biāo)題:如何理解線(xiàn)程安全?
文章出處:【微信號(hào):Linux大陸,微信公眾號(hào):Linux大陸】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
不同創(chuàng)建線(xiàn)程安全Set的方式
調(diào)用非安全線(xiàn)程的dll的問(wèn)題
Linux下的線(xiàn)程安全是什么
什么是線(xiàn)程安全?如何去實(shí)現(xiàn)線(xiàn)程安全?
請(qǐng)教大神rtthread中的ringbuff是線(xiàn)程安全的嗎
什么是線(xiàn)程安全
解決線(xiàn)程安全問(wèn)題技巧匯總
java的線(xiàn)程安全、單例模式、JVM內(nèi)存結(jié)構(gòu)
什么是線(xiàn)程安全 如何實(shí)現(xiàn)線(xiàn)程安全代碼
原理解析:線(xiàn)程池中多余的線(xiàn)程是如何回收的?
線(xiàn)程安全怎么辦
![<b class='flag-5'>線(xiàn)程</b><b class='flag-5'>安全</b>怎么辦](https://file1.elecfans.com/web2/M00/A9/51/wKgZomUk9m6AI2XCAAAfNGw41WI050.jpg)
如何知道你的代碼是否線(xiàn)程安全
![如何知道你的代碼是否<b class='flag-5'>線(xiàn)程</b><b class='flag-5'>安全</b>](https://file1.elecfans.com/web2/M00/AD/94/wKgZomVByJqATZOjAAGqxiwwwzU143.jpg)
評(píng)論