多線程訪問共享數(shù)據(jù)不安全問題分析

例:假設(shè)兩個(gè)線程t1和t2都要對(duì)num=0進(jìn)行增1運(yùn)算愕把,t1和t2都各對(duì)num修改10次拣凹,num的最終的結(jié)果應(yīng)該為20。
但是由于是多線程訪問礼华,有可能出現(xiàn)下面情況:
在num=0時(shí)咐鹤,t1取得num=0。此時(shí)系統(tǒng)把t1調(diào)度為”sleeping”狀態(tài)圣絮,把t2轉(zhuǎn)換為”running”狀態(tài)祈惶,t2也獲得num=0。
然后t2對(duì)得到的值進(jìn)行加1并賦給num扮匠,使得num=1捧请。然后系統(tǒng)又把t2調(diào)度為”sleeping”,把t1轉(zhuǎn)為”running”棒搜。
線程t1又把它之前得到的0加1后賦值給num疹蛉。這樣,明明t1和t2都完成了1次加1工作力麸,但結(jié)果仍然是num=1

1.g_num的值大部分是在一百萬到兩百萬之間的情況
from threading import Thread

g_num = 0
def test1():
    global g_num
    for i in range(1000000):
        # g_num += 1
        b = g_num + 1
        g_num = b

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    for i in range(1000000):
        a =  g_num + 1
        g_num = a

    print("---test2---g_num=%d"%g_num)


if __name__ == '__main__':
    p1 = Thread(target=test1)
    p1.start()

    p2 = Thread(target=test2)
    p2.start()
#--------------------運(yùn)行結(jié)果------------------------
---test1---g_num=1283303
---test2---g_num=1257613

Process finished with exit code 0
以上結(jié)果多個(gè)線程對(duì)同一資源的訪問可款,對(duì)數(shù)據(jù)造成破壞,使得線程運(yùn)行的結(jié)果不可預(yù)期克蚂。這種現(xiàn)象稱為“線程不安全”


2.g_num的值小于一百萬的情況
from threading import Thread
import time

g_num = 0
def test1():
    global g_num
    for i in range(1000000):
        # g_num += 1
        b = g_num + 1
        time.sleep(0.1)   #此處添加阻塞狀態(tài)闺鲸,是為了讓b結(jié)果沒有賦值給g_num就被切換到另一個(gè)函數(shù)
        g_num = b

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    for i in range(1000000):
        a =  g_num + 1
        g_num = a

    print("---test2---g_num=%d"%g_num)


if __name__ == '__main__':
    p1 = Thread(target=test1)
    p1.start()

    p2 = Thread(target=test2)
    p2.start()
#--------------------運(yùn)行結(jié)果------------------------
---test2---g_num=27712
注:此結(jié)果沒有出現(xiàn) Process finished這句話的原因是sleep 0.1 秒 還要運(yùn)行幾十萬次以上,
時(shí)間太長(zhǎng)埃叭,所以程序 test1 其實(shí)一直在運(yùn)行摸恍,只能強(qiáng)制停止程序。
跟第一個(gè)例子一樣,線程不安全


3.正常情況g_num
from threading import Thread
import time

g_num = 0

def test1():
    global g_num
    for i in range(1000000):
        # g_num += 1
        b = g_num + 1
        g_num = b

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    for i in range(1000000):
        a =  g_num + 1
        g_num = a

    print("---test2---g_num=%d"%g_num)

if __name__ == '__main__':
    p1 = Thread(target=test1)
    p1.start()
    time.sleep(1)   #此處阻塞1秒立镶,給test1充分運(yùn)行時(shí)間壁袄,直至該線程運(yùn)行結(jié)束
    p2 = Thread(target=test2)
    p2.start()
#--------------------運(yùn)行結(jié)果------------------------
---test1---g_num=1000000
---test2---g_num=2000000

Process finished with exit code 0
本應(yīng)該輸出的g_num正確值


4.解決辦法
from threading import Thread,Lock

g_num = 0
my_lock = Lock()

def test1():
    global g_num
    if my_lock.acquire():              #同步鎖防止?fàn)帄Z資源
        for i in range(1000000):
            g_num  = g_num+1
        my_lock.release()              #解鎖

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    if my_lock.acquire():
        for i in range(1000000):
            g_num  = g_num+1
        my_lock.release()

    print("---test2---g_num=%d"%g_num)


if __name__ == '__main__':
    p1 = Thread(target=test1)
    p1.start()

    p2 = Thread(target=test2)
    p2.start()
#--------------------運(yùn)行結(jié)果------------------------
---test1---g_num=1000000
---test2---g_num=2000000
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市媚媒,隨后出現(xiàn)的幾起案子嗜逻,更是在濱河造成了極大的恐慌,老刑警劉巖缭召,帶你破解...
    沈念sama閱讀 212,222評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件变泄,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡恼琼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門屏富,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晴竞,“玉大人,你說我怎么就攤上這事狠半∝溃” “怎么了?”我有些...
    開封第一講書人閱讀 157,720評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵神年,是天一觀的道長(zhǎng)已维。 經(jīng)常有香客問我,道長(zhǎng)已日,這世上最難降的妖魔是什么垛耳? 我笑而不...
    開封第一講書人閱讀 56,568評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮飘千,結(jié)果婚禮上堂鲜,老公的妹妹穿的比我還像新娘。我一直安慰自己护奈,他們只是感情好缔莲,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霉旗,像睡著了一般痴奏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厌秒,一...
    開封第一講書人閱讀 49,879評(píng)論 1 290
  • 那天读拆,我揣著相機(jī)與錄音,去河邊找鬼简僧。 笑死建椰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的岛马。 我是一名探鬼主播棉姐,決...
    沈念sama閱讀 39,028評(píng)論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼屠列,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了伞矩?” 一聲冷哼從身側(cè)響起笛洛,我...
    開封第一講書人閱讀 37,773評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乃坤,沒想到半個(gè)月后苛让,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡湿诊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評(píng)論 2 327
  • 正文 我和宋清朗相戀三年狱杰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厅须。...
    茶點(diǎn)故事閱讀 38,697評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仿畸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出朗和,到底是詐尸還是另有隱情错沽,我是刑警寧澤,帶...
    沈念sama閱讀 34,360評(píng)論 4 332
  • 正文 年R本政府宣布眶拉,位于F島的核電站千埃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏忆植。R本人自食惡果不足惜放可,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唱逢。 院中可真熱鬧吴侦,春花似錦、人聲如沸坞古。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痪枫。三九已至织堂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奶陈,已是汗流浹背易阳。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吃粒,地道東北人潦俺。 一個(gè)月前我還...
    沈念sama閱讀 46,433評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親事示。 傳聞我的和親對(duì)象是個(gè)殘疾皇子早像,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 1.多任務(wù) 在計(jì)算機(jī)中,操作系統(tǒng)可以同時(shí)運(yùn)行多個(gè)任務(wù),這就是多任務(wù)肖爵。那么如何解決多個(gè)任務(wù)同時(shí)運(yùn)行呢卢鹦,那就需要用到多...
    瀟瀟雨歇_安然閱讀 371評(píng)論 0 1
  • 1.進(jìn)程和線程 隊(duì)列:1、進(jìn)程之間的通信: q = multiprocessing.Queue()2劝堪、...
    一只寫程序的猿閱讀 1,103評(píng)論 0 17
  • 線程 1.同步概念 1.多線程開發(fā)可能遇到的問題 同步不是一起的意思冀自,是協(xié)同步調(diào) 假設(shè)兩個(gè)線程t1和t2都要對(duì)nu...
    TENG書閱讀 606評(píng)論 0 1
  • 多任務(wù)可以由多進(jìn)程完成,也可以由一個(gè)進(jìn)程內(nèi)的多線程完成秒啦。我們前面提到了進(jìn)程是由若干線程組成的熬粗,一個(gè)進(jìn)程至少有一個(gè)線...
    壁花燒年閱讀 813評(píng)論 0 0
  • 2016/12/11 [ ] 早上七點(diǎn)半起床,沒有吃早餐余境,吃了一個(gè)面包就出門去附屬口腔醫(yī)院看牙齒荐糜,咨詢牙齒正畸。路...
    丁昱研閱讀 147評(píng)論 0 0