• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            桃源谷

            心靈的旅行

            人生就是一場旅行,不在乎旅行的目的地,在乎的是沿途的風景和看風景的心情 !
            posts - 32, comments - 42, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            準則4:請不要做線程的異步撤消的設計

            Posted on 2008-12-19 11:01 lymons 閱讀(1279) 評論(0)  編輯 收藏 引用 所屬分類: C++ 、C 、Unix/Linux 、文章翻譯
            From 2008精選

            原文地址:http://d.hatena.ne.jp/yupo5656/20040724/p1

            [] UNIX上的C++程序設計守則 (4)Add star

            鐵則4: 請不要做線程的異步撤消的設計

            • 線程的異步撤銷是指: 某個線程的執行立刻被其他線程給強制終止了
            • 請不要單單為了讓“設計更簡單”或者“看起了更簡單”而使用線程的異步撤消

            咋一看還是挺簡單的。但是搞不好可能會引起各種各樣的問題。請不要在不能把握問題的實質就做出使用線程的異步撤消的設計!

            在pthread的規格說明中,允許一個線程可以強制中斷某個線程的執行。這就是所說的異步撤消。


            線程的撤消有下面的兩種方式。

            • 方式1: 異步撤消(PTHREAD_CANCEL_ASYNCHRONOUS)
              • 撤銷動作是馬上進行的
            • 方式2: 延遲撤銷(PTHREAD_CANCEL_DEFERRED)
              • 撤消動作,是讓線程的處理一直被延遲到撤消點才會去執行

            還有,到底是用哪種撤消方式,不是撤消側,而是被撤銷側能夠決定的*1。另外,在被撤銷側也能夠選擇完全禁止撤消的這種方式 *2。


            會造成什么問題呢

            那么,讓我看看亂用線程的異步撤消會引起什么問題呢??催^準則3的人可能會知道,在下面的腳本里,被撤銷線程以外的任意一個線程會被死鎖。

            1. 線程1中調用malloc函數正在做內存分配的過程中,線程2異步撤消了線程1的處理
            2. 線程1馬上被撤銷,但是malloc函數中的互斥鎖就沒有線程去解除了
            3. 后面的任意一個線程如果再次調用malloc函數的話就會馬上導致該線程死鎖

            在這個例子中使用了malloc函數,但是其他的危險函數還有很多。


            反之,即使做了異步撤消也沒有問題的函數也有少數存在的、我們把它們叫做「async-cancel safe函數」或者「異步撤消安全函數」。在一些商用UNIX*3中、OS提供的api函數的文檔說明中有async-cancel safety的記載、但是在Linux(glibc)里就很遺憾,幾乎沒有相關的說明。


            在這兒,參看規格(SUSv3)的話,會發現,、描述異步撤消安全的函數只有3個。

            1. pthread_cancel
            2. pthread_setcancelstate
            3. pthread_setcanceltype

            而且、里面還有"No other functions are required to be async-cancel-safe"這樣的記載。因此,Linux的場合,如果在文檔里沒有記載成async-cancel safety的函數,我們還是把它假定成不安全的函數為好!


            如何避免這些問題呢

            在多線程編程中為了安全的使用異步撤消處理、有沒有回避死鎖的方法呢?我們試著想了幾個。他們與準則3里的線程+fork的場合的回避策很相似。


            回避方法1: 被撤銷線程中,只能使用異步撤消安全函數


            首先,被撤銷線程中,只能使用異步撤消安全函數。但是這個方法

            • 在規格說明中只有3個異步撤消安全的函數
            • 這些以外的函數是不是異步撤消安全(商用UNIX)、因為沒有說明文檔我們不清楚(Linux)

            中有以上的兩點,所以這個回避方法幾乎不現實。


            回避方法2: 被撤銷線程中,在做非異步撤消安全處理的過程中,再把撤消方式設置成「延遲」或者是「禁止」


            第二個是,被撤銷線程在做非異步撤消安全處理的過程中,把撤消方式再設定成「延遲」或者「禁止」。對于這個方法

            • 就像方法1寫的那樣、要把我那個函數是異步撤消安全的一時還是挺麻煩的
            • 在任意的場所并不能保證撤消動作會被馬上執行
              • 例如,再設定成「延遲」后的一段時間內如果撤消發生時、某個正在阻塞的I/O函數是否能夠被解除阻塞還是挺微妙的
              • 如果設定成撤消禁止的話,則撤消會被屏蔽掉

            有上面樣的問題、會導致「一精心設計撤消方式的替換,從一開始就使用延遲撤消還不夠好」這樣的結果。所以這幾乎是不好的一個回避策。


            回避方法3: 使用pthread_cleanup_push函數,登錄異步撤消時的線程數據清除的回調函數


            第三種則是,用pthread_cleanup_push函數、登錄一個在異步撤消發生時的數據清除的回調函數。這和在準則3中介紹的pthread_atfork函數有點兒類似。用這個函數登錄的回調函數來清除線程的數據和鎖,就可以回避死鎖了。


            ...但是,pthread_cleanup_push函數登錄的回調函數,在「延遲撤消」的場合是不能被調用的。因此、這個回避方法對于異步撤消沒有什么大的作用。


            回避方法4: 不要執行異步撤消處理


            最后是、不要執行異步撤消處理。反而代之的是、

            • 設計成不依賴使用異步撤消那樣的處理

            或者

            • 不得不使用線程撤消的話、不做異步撤消而作延遲撤消的處理

            這是比較實際的做法,是我們值得推薦的。

            *1:pthread_setcanceltype函數

            *2:pthread_setcancelstate函數

            *3:Solaris和HP-UX等

            我的個人簡歷第一頁 我的個人簡歷第二頁
            久久不射电影网| 91精品国产高清久久久久久国产嫩草| 国产精品久久成人影院| 天堂久久天堂AV色综合| 久久婷婷综合中文字幕| 97精品伊人久久大香线蕉| 久久精品亚洲乱码伦伦中文| 久久狠狠爱亚洲综合影院| 久久亚洲中文字幕精品有坂深雪| 国内精品久久久久影院日本 | 久久精品毛片免费观看| 久久国产精品成人影院| 久久精品国产亚洲麻豆| 久久精品国产一区二区 | 久久无码AV一区二区三区| 久久人妻AV中文字幕| 久久免费精品视频| 欧美日韩精品久久久久| 国产L精品国产亚洲区久久| 久久综合亚洲欧美成人| 久久久久久无码国产精品中文字幕 | 久久精品国产99久久久| 99久久精品无码一区二区毛片| 热久久最新网站获取| 99精品久久久久久久婷婷| 久久天堂AV综合合色蜜桃网 | 中文字幕无码久久精品青草| 四虎久久影院| 91精品国产乱码久久久久久| 婷婷久久综合九色综合九七| 久久久久女人精品毛片| 国产激情久久久久影院老熟女| 久久精品国产久精国产思思| 国产精品99久久不卡| 狠狠干狠狠久久| 97精品久久天干天天天按摩| 亚洲综合精品香蕉久久网| 色综合久久无码中文字幕| 亚洲AV日韩AV永久无码久久| 久久久久亚洲AV片无码下载蜜桃| 亚洲欧美一区二区三区久久|