5天不再懼怕多執行緒 第二天 鎖機制

2021-08-26 18:54:55 字數 4817 閱讀 9349

當多個執行緒在併發的時候,難免會碰到相互衝突的事情,比如最經典的atm機的問題,併發不可怕,可怕的是我們沒有能力控制。

執行緒以我的理解可以分為三種

① 鎖。

② 互斥。

③ 訊號。

好,這一篇主要整理「鎖」,c#提供了2種手工控制的鎖

一:  monitor類

這個算是實現鎖機制的純正類,在鎖定的臨界區中只允許讓乙個執行緒訪問,其他執行緒排隊等待。主要整理為2組方法。

1:monitor.enter和monitor.exit

微軟很照護我們,給了我們語法糖lock,對的,語言糖確實減少了我們不必要的勞動並且讓**更可觀,但是如果我們要精細的

控制,則必須使用原生類,這裡要注意乙個問題就是「鎖住什麼」的問題,一般情況下我們鎖住的都是靜態物件,我們知道靜態物件

屬於類級別,當有很多執行緒共同訪問的時候,那個靜態物件對多個執行緒來說是乙個,不像例項欄位會被認為是多個。

不加鎖的情況:

1

class program

2

11 }

1213

//資源

14static

object obj = new

object();

1516

static

int count = 0;

1718

static

void run()

19

", ++count);

23 }

24 }

複製**

加鎖的情況:

1

class program

2

11 }

1213

//資源

14static

object obj = new

object();

1516

static

int count = 0;

1718

static

void run()

19

", ++count);

2627

//退出臨界區

28 monitor.exit(obj);

29 }

30 }

複製**

2:monitor.wait和monitor.pulse

首先這兩個方法是成對出現,通常使用在enter,exit之間。

wait: 暫時的釋放資源鎖,然後該執行緒進入」等待佇列「中,那麼自然別的執行緒就能獲取到資源鎖。

pulse:  喚醒「等待佇列」中的執行緒,那麼當時被wait的執行緒就重新獲取到了鎖。

這裡我們是否注意到了兩點:

①   可能a執行緒進入到臨界區後,需要b執行緒做一些初始化操作,然後a執行緒繼續幹剩下的事情。

②   用上面的兩個方法,我們可以實現執行緒間的彼此通訊。

下面舉個例子來模擬兩個人的對話。

1

using system;

2using system.collections.generic;

3using system.text;

4using system.threading;56

namespace test

7 29 }

3031

//鎖定物件

32public

class lockobj

3334

public

class jack

35

4243

public

void run()

44 :我已進入茅廁。

", thread.currentthread.name);

4849 console.writeline("

:擦,太臭了,我還是撤!

", thread.currentthread.name);

5051

//暫時的釋放鎖資源

52 monitor.wait(this.obj);

5354 console.writeline("

:兄弟說的對,我還是進去吧。

", thread.currentthread.name);

5556

//喚醒等待佇列中的執行緒

57 monitor.pulse(this.obj);

5859 console.writeline("

:拉完了,真舒服。

", thread.currentthread.name);

6061 monitor.exit(this.obj);

62 }

63 }

6465

public

class john

66

7374

public

void run()

75 :直奔茅廁,兄弟,你還是進來吧,小心憋壞了!

",79 thread.currentthread.name);

8081

//喚醒等待佇列中的執行緒

82 monitor.pulse(this.obj);

8384 console.writeline("

:嘩啦啦....

", thread.currentthread.name);

8586

//暫時的釋放鎖資源

87 monitor.wait(this.obj);

8889 console.writeline("

:拉完了,真舒服。

", thread.currentthread.name);

9091 monitor.exit(this.obj);

92 }

93 }

94 }

複製**

二:readerwriterlock類

先前也知道,monitor實現的是在讀寫兩種情況的臨界區中只可以讓乙個執行緒訪問,那麼如果業務中存在」讀取密集型「操作,就

好比資料庫一樣,讀取的操作永遠比寫入的操作多。針對這種情況,我們使用monitor的話很吃虧,不過沒關係,readwriterlock

就很牛x,因為實現了」寫入序列「,」讀取並行「。

readerwritelock中主要用3組方法:

<1>  acquirewriterlock: 獲取寫入鎖。

releasewriterlock:釋放寫入鎖。

<2>  acquirereaderlock: 獲取讀鎖。

releasereaderlock:釋放讀鎖。

<3>  upgradetowriterlock:將讀鎖轉為寫鎖。

downgradefromwriterlock:將寫鎖還原為讀鎖。

下面就實現乙個寫操作,三個讀操作,要知道這三個讀操作是併發的。

1

namespace test

2 21

22///

23///

模擬3s插入一次

24///

25///

26public

static

void autoaddfunc()

27

3132

public

static

void autoreadfunc()

33

3940

public

static

void add(object obj)

41 ,我插入的資料是。

", thread.currentthread.managedthreadid, num);

5051

//釋放鎖

52 rw.releasewriterlock();

53 }

5455

public

static

void read(object obj)

56 ,我讀取的集合為:

",61 thread.currentthread.managedthreadid, string.join("

,", list));

62//

釋放鎖63 rw.releasereaderlock();

64 }

65 }

66 }

複製**

mysql第二天 鎖

如果沒有鎖,那麼併發性會更強,但是資料安全性會有問題。因此資料庫會給資料加鎖。也就是讀寫鎖,共享鎖可以疊加共享鎖但是不能加排他鎖,排他鎖則不能疊加。根據隔離級別等等,mysql會隱式的給資料自動加鎖 此外還可以使用share in model,for update 等語句顯示的加鎖粒度越細,維護鎖的...

5天不再懼怕多執行緒 第三天 互斥體

沒想到我的前兩篇文章還挺受歡迎的,謝謝大家,今天整理下mutex的使用。一 mutex 首先看下msdn對它的解釋 不錯,出現了乙個亮點,可用於 程序間同步 既然程序間都可以同步,那執行緒同步對它來說不是小菜一碟嗎?好的,還是看下mutex在 執行緒中發揮的神奇功效。1 執行緒間同步 metux中提...

5天不再懼怕多執行緒 第一天 嘗試Thread

原本準備在mongodb之後寫乙個lucene.net系列,不過這幾天用到多執行緒時才發現自己對多執行緒的了解少之又少,僅僅停留在lock上面,好了,我們知道 負載 是乙個很時尚,很牛x的玩意,往大處說,需要負載,資料庫需要負載。往小處說,執行緒也需要負載,面對海量的 使用者請求,我們的單執行緒肯定...