<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    一江春水向東流

    做一個(gè)有思想的人,期待與每一位熱愛思考的人交流,您的關(guān)注是對(duì)我最大的支持。

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      44 隨筆 :: 139 文章 :: 81 評(píng)論 :: 0 Trackbacks
    使用線程編寫程序需要技巧,而多線程的程序中的bug非常難以跟蹤、調(diào)試,因?yàn)檫@些bug經(jīng)常是難以再現(xiàn)的。

    競(jìng)爭(zhēng)條件

    當(dāng)一個(gè)線程訪問一個(gè)數(shù)據(jù)結(jié)構(gòu)的時(shí)候,另一個(gè)線程也訪問同一個(gè)數(shù)據(jù)結(jié)構(gòu),這時(shí)就出現(xiàn)了競(jìng)爭(zhēng)條件——兩個(gè)線程(也可能是多個(gè))競(jìng)爭(zhēng)對(duì)同一個(gè)資源的訪問。
    當(dāng)其中一個(gè)線程處理到一部分的時(shí)候,另外的線程可能進(jìn)入了對(duì)同一數(shù)據(jù)的處理,而且出于調(diào)度的原因,它運(yùn)行的比前一個(gè)更快;這時(shí),同樣的處理可能就出現(xiàn)了多次。
    例如,一個(gè)代表任務(wù)列表的單向鏈表(隊(duì)列),一個(gè)線程從當(dāng)前元素中讀出了下一個(gè)任務(wù),并發(fā)現(xiàn)下一個(gè)任務(wù)不是空,準(zhǔn)備將此一個(gè)任務(wù)置為NULL并執(zhí)行任務(wù);這時(shí),調(diào)度使得這個(gè)線程停下來,另一個(gè)線程也從當(dāng)前元素中讀出了下一個(gè)任務(wù),當(dāng)然下個(gè)任務(wù)仍然不是空值,這個(gè)線程也將要執(zhí)行下一個(gè)任務(wù)。這樣,在某些不幸的情況下,這個(gè)任務(wù)被執(zhí)行了兩次。
    更為不幸的情況下,執(zhí)行任務(wù)的過程中線程被中斷,此時(shí)另一個(gè)線程釋放了任務(wù)的內(nèi)存,那么執(zhí)行中的線程會(huì)導(dǎo)致段錯(cuò)誤。
    在比較“幸運(yùn)”的情況下,這些事情可能從來也不發(fā)生;但是當(dāng)程序運(yùn)行在負(fù)荷很高的系統(tǒng)中時(shí),這個(gè)bug就會(huì)凸現(xiàn)出來。

    互斥鎖
    為了排除競(jìng)爭(zhēng)條件的影響,應(yīng)該使一些操作變成“原子的”——這些操作既不能分割也不能中斷。
    當(dāng)一個(gè)線程鎖定了互斥鎖后,其他線程也要求鎖定這個(gè)互斥鎖的時(shí)候,就會(huì)被阻塞;直到前面的線程解除鎖定后,其他線程才可以解除阻塞恢復(fù)運(yùn)行。
    GNU/Linux保證線程在鎖定互斥鎖的過程中不會(huì)發(fā)生競(jìng)爭(zhēng)條件,只有一個(gè)線程可以鎖定互斥鎖,其他線程的鎖定請(qǐng)求都會(huì)被阻塞。

    創(chuàng)建互斥鎖(Mutex),需要:
    `創(chuàng)建一個(gè)pthread_mutex_t類型的變量,將其指針傳入函數(shù)pthread_mutex_init中;該函數(shù)的第二個(gè)參數(shù)是指向一個(gè)mutex屬性對(duì)象(這個(gè)對(duì)象用來指定mutex的屬性)的指針。mutex對(duì)象只能初始化一次。
    `更簡(jiǎn)單的辦法是,使用PTHREAD_MUTEX_INITIALIZER來獲得默認(rèn)屬性的mutex對(duì)象:
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    使用mutex:
    `調(diào)用pthread_mutex_lock函數(shù),如果mutex對(duì)象未被鎖定,則此函數(shù)立即返回;如果已被鎖定,則此函數(shù)阻塞此線程的執(zhí)行,直到mutex被解除鎖定。
    `每次解除鎖定后,只有一個(gè)線程可以解除阻塞恢復(fù)執(zhí)行,其他調(diào)用線程都會(huì)繼續(xù)阻塞。選定的解除阻塞的線程是不可預(yù)知的。
    `調(diào)用pthread_mutex_unlock函數(shù),可以解除調(diào)用線程對(duì)mutex對(duì)象的鎖定。在鎖定mutex的線程中,必須調(diào)用此函數(shù)以解除鎖定。

    mutex提供了解決競(jìng)爭(zhēng)條件的方案,但是它帶來了一種新的bug——死鎖deadlock)。
    所謂死鎖,就是說一個(gè)線程在等待永遠(yuǎn)不會(huì)發(fā)生的條件。
    一個(gè)簡(jiǎn)單的死鎖:一個(gè)線程鎖定它自己已經(jīng)鎖定的mutex。這時(shí)程序的表現(xiàn)依賴于mutex的類型:
    `快速排他鎖(fast mutex)——導(dǎo)致死鎖。
    `遞歸排他鎖(recursive mutex)——不導(dǎo)致死鎖。同一個(gè)線程可以安全的多次鎖定同一個(gè)已鎖定的mutex,但是鎖定的次數(shù)會(huì)被記錄下來,該線程還必須調(diào)用相應(yīng)次數(shù)的pthread_mutex_unlock才能真正解除對(duì)mutex的鎖定。
    `檢錯(cuò)排他鎖(error-checking mutex)——GNU/Linux視此操作為死鎖,但是對(duì)鎖定的mutex調(diào)用pthread_mutex_lock函數(shù),函數(shù)立即返回錯(cuò)誤碼EDEADLK。

    mutex的鎖定函數(shù)會(huì)阻塞,有時(shí)需要一個(gè)不阻塞就能知道m(xù)utex是否已鎖定的函數(shù),以在發(fā)現(xiàn)mutex已鎖的情況下去完成其他工作并在以后再來檢查。這樣的函數(shù)是:
    pthread_mutex_trylock
    如果傳入的mutex已經(jīng)被其他線程鎖定,那么這個(gè)函數(shù)返回錯(cuò)誤碼EBUSY;如果未被鎖定,此函數(shù)會(huì)鎖定mutex,并返回0。這個(gè)函數(shù)不會(huì)阻塞。
    posted on 2008-02-15 10:15 allic 閱讀(1411) 評(píng)論(0)  編輯  收藏 所屬分類: C/C++
    主站蜘蛛池模板: 国产成人亚洲午夜电影| 又爽又黄无遮挡高清免费视频| 日本永久免费a∨在线视频| 亚洲日本国产精华液| 亚洲中文字幕无码一区二区三区 | 成年美女黄网站色大免费视频| 亚洲黄片手机免费观看| 亚洲GV天堂无码男同在线观看| 亚洲另类小说图片| 亚洲人成亚洲精品| 亚洲色偷偷综合亚洲AVYP| 亚洲AV无码之日韩精品| 24小时日本在线www免费的| 亚洲免费福利视频| 95老司机免费福利| 免费人成网站在线观看不卡| 中文在线观看永久免费| 人成电影网在线观看免费| 亚洲AV永久无码精品放毛片| 亚洲娇小性色xxxx| 2019亚洲午夜无码天堂| tom影院亚洲国产一区二区| 亚洲小说区图片区| 亚洲六月丁香六月婷婷色伊人 | 久久久久久久久久久免费精品 | 国产精品亚洲视频| 免费大黄网站在线观| 全黄性性激高免费视频| 丁香亚洲综合五月天婷婷| 免费A级毛片无码久久版| 四虎影视在线永久免费看黄| 日本不卡在线观看免费v| 男女交性永久免费视频播放| 免费观看美女裸体网站| 又色又污又黄无遮挡的免费视| 国产大片线上免费看| 国产一区二区视频免费| 亚洲国产午夜中文字幕精品黄网站| 亚洲国产精品成人一区| 国产成人亚洲影院在线观看| 国产成人亚洲综合无码|