C 多執行緒學習(五)執行緒同步和衝突解決

2021-08-03 09:45:15 字數 3958 閱讀 1374

首先先說乙個執行緒不同步的例子吧,以下為售票員的模擬售票,多個售票員**100張門票,**如下:

using system;

using system.text;

using system.collections.generic;

using system.threading;

namespace threadtest

public

void

start()

thread_1.start();

thread_2.start();

}public

void

run()

sail a ticket ,ticket number : ",

thread.currentthread.name, get.tostring());

tickets.removeat(0);

thread.sleep(1);}}

}static

void main()}}

以上為乙個模擬售票系統,兩個執行緒對乙個票箱進行操作,每次都取出最上層的票,然後輸出,執行之後檢視結果會發現在在同一張票上,兩個執行緒都可能同時賣出,如下:

出現以上的情況的原因就是在多執行緒的的情況之下,執行緒的執行順序是不可控的,就可能會出現以上的情況,具體原因可能如下:

請看**:

int get = tickets[0];

console.writeline(" sail a ticket ,ticket number : ",

thread.currentthread

.name, get.tostring());

tickets.removeat(0);

比如,執行緒a在剛從tickets中確定要取最底下的一張票之後還未將這張票輸出並刪除,這時候執行緒a被分配的cpu時間就用光了。

然後輪到另乙個執行緒b執行,執行緒b的時間充足,也同樣確認了執行緒a剛才確定的那張票,然後取出了那張票,取出然後輸出並刪除掉那張票,然後將cpu控制權交到了執行緒a上。

又輪到了執行緒a執行,執行緒a由於剛才已經確定了選定的票號,所以直接輸出了那個票號,然後將最底下的票刪除。所以可以看到取票有一段是跳躍著取得,如:1,3,5,7,…

出現這種情況的原因就是多個執行緒都是對同乙個資源進行操作所致,所以在多執行緒程式設計應盡可能避免這種情況,當然有些情況下確實避免不了這種情況,這就需要對其採用一些手段來確保不會出現這種情況,這就是所謂的執行緒的同步

在c#中實現執行緒的同步有幾種方法:lock、mutex、monitor、semaphore、interlockedreaderwriterlock等。同步策略也可以分為同步上下文、同步**區、手動同步幾種方式。

針對上面的**,要保證不會出現混亂的情況,可以用lock關鍵字來實現,出現問題的部分就是在於判斷剩餘票數是否大於0,如果大於0則從當前總票數中減去最大的一張票,因此可以對這部分進行lock處理,**如下:

public

void

run()

sail a ticket ,ticket number : ",

thread.currentthread.name, get.tostring());

tickets.removeat(0);

thread.sleep(1);}}

}}

這樣處理之後,這個售票系統就變得正常了,效果如下:

總的來說,lock語句是一種有效的、不跨越多個方法的小**塊同步的做法,也就是使用lock語句只能在某個方法的部分**之間,不能跨越方法。

針對以上的處理方法,我們用monitor類來處理的話是如下**:

public void run()

sail a ticket ,ticket number : ",

thread.currentthread

.name, get.tostring());

tickets.removeat(0);

thread.sleep(1);}}

monitor.exit(objlock);

}

執行可以知道,這段**和lock方法的結果是一樣的,當然其實lock就是用monitor類實現的,除了鎖定**區,我們還可用monitor類的wait()和 pulse()方法。

wait()方法是臨時釋放當前活得的鎖,並使當前物件處於阻塞狀態

pulse()方法是通知處於等待狀態的物件可以準備就緒了,它一會就會釋放鎖。

下面我們來實現乙個生產者和消費者模式,生產者執行緒負責生產資料,消費者執行緒將生產者生產出來的資料輸出,**如下:

using system;

using system.text;

using system.collections.generic;

using system.threading;

namespace threadtest

catch (synchronizationlockexception e)

}console.writeline("use: ", cellcontents);

readerflag = false;

//重置readerflag標誌,表示消費行為已經完成

monitor.pulse(this);

//通知writetocell()方法(該方法在另外乙個執行緒中執行,等待中)

}return cellcontents;

}public

void

writetocell(int n)

catch (synchronizationlockexception e)

}cellcontents = n;

console.writeline("produce: ", cellcontents);

readerflag = true;

monitor.pulse(this);

//通知另外乙個執行緒中正在等待的readfromcell()方法}}

}public

class cellprod

public

void

threadrun()

}public

class cellcons

public

void

threadrun()

}public

static

void

main(string args)

catch (threadstateexception e)}}

}

這個例程中,生產者執行緒和消費者執行緒是交替進行的,生產者寫入乙個數,消費者立即讀取並輸出。

同步是通過等待monitor.pulse()來完成的。

首先生產者生產了乙個資料,而同一時刻消費者處於等待狀態,直到收到生產者的「脈衝(pulse)」通知它生產已經完成,此後消費者進入消費狀態。迴圈往復,效果如下:

差不多如此吧,上面的方法已經可以幫助我們解決多執行緒中可能出現的大部分問題,剩下的就不再介紹了,同步的處理也到此結束了。

LINUX執行緒(五)執行緒同步

執行緒同步,指乙個執行緒發出同一功能呼叫時,在沒有得到結果之前,該呼叫不返回。同時其他執行緒為保證資料一致性,不能呼叫該功能 鎖的使用 建議鎖,對公共資料進行保護,所有執行緒應該在訪問公共資料前先拿鎖再訪問,但鎖本身不具備強制性 pthread mutex t mutex phtread mutex...

多執行緒(五) 執行緒的通訊

例題 使用兩個執行緒列印1 100。執行緒1,執行緒2交替列印。執行緒通訊的例子 使用兩個執行緒列印1 100.執行緒1,執行緒2,交替列印。class number implements runnable catch interruptedexception e system.out.printl...

linux多執行緒學習筆記五 執行緒安全

一,執行緒安全基礎 乙個函式被稱為執行緒安全的當且僅當被多個併發執行緒反覆呼叫時,它會一直產生正確的結果。我們能夠定義出四類執行緒不安全函式。第一類 不保護共享變數的函式 共享變數在多執行緒中是共享資料,可以通過同步機制來保護共享資料。第二類 保護跨越多個呼叫狀態的函式 乙個偽隨機數生成器是乙個簡單...