多線程的那點事兒(之資料互斥)

來源:互聯網
上載者:User

【 聲明:著作權,歡迎轉載,請勿用於商業用途。  聯絡信箱:feixiaoxing @163.com】

 

    在多線程存在的環境中,除了堆棧中的臨時資料之外,所有的資料都是共用的。如果我們需要線程之間正確地運行,那麼務必需要保證公用資料的執行和計算是正確的。簡單一點說,就是保證資料在執行的時候必須是互斥的。否則,如果兩個或者多個線程在同一時刻對資料進行了操作,那麼後果是不可想象的。

    也許有的朋友會說,不光資料需要保護,代碼也需要保護。提出這個觀點的朋友只看到了資料訪問互斥的表象。在程式的Runspace裡面,什麼最重要的呢?代碼嗎?當然不是。代碼只是為了資料的訪問存在的。資料才是我們一切工作的出發點和落腳點。

    那麼,有什麼辦法可以保證在某一時刻只有一個線程對資料進行操作呢?四個基本方法:

    (1)關中斷

    (2)數學互斥方法

    (3)作業系統提供的互斥方法

    (4)cpu原子操作

    為了讓大家可以對這四種方法有詳細的認識,我們可以進行詳細的介紹。

  

    (1)關中斷

    要讓資料在某一時刻只被一個線程訪問,方法之一就是停止線程調度就可以了。那麼怎樣停止線程調度呢?那麼關掉時鐘中斷就可以了啊。在X86裡面的確存在這樣的兩個指令,

#include <stdio.h>int main(){__asm{clisti}return 1;}

    其中cli是關中斷,sti是開中斷。這段代碼沒有什麼問題,可以編過,當然也可以產生執行檔案。但是在執行的時候會出現一個異常警示:Unhandled exception in test.exe: 0xC0000096:  Privileged Instruction。警示已經說的很清楚了,這是一個特權指令。只有系統或者核心本身才可以使用這個指令。

    不過,大家也可以想象一下。因為平常我們編寫的程式都是應用層級的程式,要是每個程式都是用這些代碼,那不亂了套了。比如說,你不小心安裝一個低品質的軟體,說不定什麼時候把你的中斷關了,這樣你的網路就斷了,你的輸入就沒有回應了,你的音樂什麼都沒有了,這樣的環境你受的了嗎?應用程式層的軟體是千差萬別的,軟體的水平也是參差不齊的,所以系統不可能相信任何一個私人軟體,它相信的只是它自己。

 

    (2)數學方法

    假設有兩個線程(a、b)正要對一個共用資料進行訪問,那麼怎麼做到他們之間的互斥的呢?其實我們可以這麼做,

unsigned int flag[2] = {0};unsigned int turn = 0;void process(unsigned int index){flag[index] = 1;turn =  index;while(flag[1 - index] && (turn ==  index));do_something();flag[index] = 0;}

    其實,學過作業系統的朋友都知道,上面的演算法其實就是Peterson演算法,可惜它只能用於兩個線程的資料互斥。當然,這個演算法還可以推廣到更多線程之間的互斥,那就是bakery演算法。但是數學演算法有兩個缺點:

    a)佔有空間多,兩個線程就要flag佔兩個單位空間,那麼n個線程就要n個flag空間,

    b)代碼編寫複雜,考慮的情況比較複雜

 

    (3)系統提供的互斥演算法

    系統提供的互斥演算法其實是我們平時開發中用的最多的互斥工具。就拿windows來說,關於互斥的工具就有臨界區、互斥量、訊號量等等。這類演算法有一個特點,那就是都是依據系統提高的互斥資源,那麼系統又是怎麼完成這些功能的呢?其實也不難。

    系統加鎖過程,

void Lock(HANDLE hLock){__asm {cli};while(1){if(/* 鎖可用*/){/* 設定標誌,表明當前鎖已被佔用 */__asm {sti};return;}__asm{sti};schedule();__asm{cli};}}

    系統解鎖過程,

void UnLock(HANDLE hLock){__asm {cli};/* 設定標誌, 當前鎖可用 */__asm{sti};}

    上面其實討論的就是一種最簡單的系統鎖情況。中間沒有涉及到就緒線程的壓入和彈出過程,沒有涉及到資源個數的問題,所以不是很複雜。朋友們仔細看看,應該都可以明白代碼錶達的是什麼意思。

 

    (4)CPU的原子操作
    因為在多線程操作當中,有很大一部分是比較、自增、自減等簡單操作。因為需要互斥的代碼很少,所以使用互斥量、訊號量並不合算。因此,CPU廠商為了開發的方便,把一些常用的指令設計成了原子指令,在windows上面也被稱為原子鎖,常用的原子操作函數有

InterLockedAddInterLockedExchangeInterLockedCompareExchangeInterLockedIncrementInterLockedDecrementInterLockedAndInterLockedOr

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.