當多個執行緒在併發的時候,難免會碰到相互衝突的事情,比如最經典的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的玩意,往大處說,需要負載,資料庫需要負載。往小處說,執行緒也需要負載,面對海量的 使用者請求,我們的單執行緒肯定...