對於資料庫中,為資料或是訪問資料的函式加鎖是常見的,但是在c#中資料的同步加鎖機制是什麼樣呢?
在多執行緒中,為了使資料保持一致性必須要對資料或是訪問資料的函式加鎖,在資料庫中這是很常見的,但是在程式中由於大部分都是單執行緒的程式,所以沒有加鎖的必要,但是在多執行緒中,為了保持資料的同步,一定要加鎖,好在framework中已經為我們提供了三個加鎖的機制,分別是monitor類、lock關鍵字和mutex類。
鎖定機制最簡單的做法就是使用鎖定關鍵字lock。lock關鍵字英文中就是鎖的意思,顧名思義就是為操作加上一把鎖。它的語法如下:
lock(lockobj)lockobj在這裡就是乙個鎖物件,它可以是任何物件(系統在記憶體中建立物件時會對每乙個物件加上乙個鎖標誌變數來模擬一把「鎖」,這個變數的值決定鎖開還是鎖關,也因此原則上任何引用型別的物件都可以作為鎖),它起到我們房門上鎖的作用。執行緒要執行lock裡面的語句之前先要檢查一下這把鎖是不是鎖定狀態。如果是鎖定狀態那麼這個執行緒就只好等待,如果不是鎖定狀態那麼執行緒就把其置為鎖定狀態然後操作lock裡面的語句,執行完後退出lock語句時,鎖定物件的狀態會自動變回非鎖定狀態。
例如下面程式:由於這種程式都是毫秒級的,所以執行下面的程式可能在不同的機器上有不同的結果,在同一臺機器上不同時刻執行也有不同的結果,我的測試環境為vs2005, windowsxp , cpu3.0 , 1 g monery。
程式中有兩個執行緒thread1、thread2和乙個testfunc函式,testfunc會列印出呼叫它的執行緒名和呼叫的時間(mm級的),兩個執行緒分別以30mm和100mm來呼叫testfunc這個函式。testfunc執行的時間為50mm。程式如下:
using system;
using system.collections.generic;
using system.text;
using system.threading;
namespace monitorlockmutex
public program()
public void runthread()
private void thread1func()
}private void thread2func()
}private void testfunc(string str)
", str, system.datetime.now.millisecond.tostring());
thread.sleep(50);}}
}
執行結果如下:
可以看出如果不加鎖的話,這兩個執行緒基本上是按照各自的時間間隔+testfunc的執行時間(50mm)對testfunc函式進行讀取。因為執行緒在開始時需要分配記憶體,所以第0次的呼叫不準確,從第1~9次的呼叫可以看出,thread1的執行間隔約是80mm,thread2的執行間隔約是150mm。
現在將testfunc修改如下:
private void testfunc(string str)
", str, system.datetime.now.millisecond.tostring());
thread.sleep(50);}}
或者是用monitor也是一樣的,如下:
private void testfunc(string str)
", str,system.datetime.now.millisecond.tostring());
thread.sleep(50);
monitor.exit(this);
}
其中enter和exit都是monitor中的靜態方法。
執行lock結果如下:
讓我們分析一下結果,同樣從第1次開始。相同執行緒間的呼叫時間間隔為執行緒執行時間+testfunc呼叫時間,不同執行緒間的呼叫時間間隔為testfunc呼叫時間。例如:連續兩次呼叫thread1之間的時間間隔約為30+50=80;連續兩次呼叫thread2之間的時間間隔約為100+50=150mm。呼叫thread1和thread2之間的時間間隔為50mm。因為testfunc被lock住了,所以乙個thread呼叫testfunc後,當其它的執行緒也同時呼叫testfunc時,後來的執行緒即進被排到等待佇列中等待,直到擁有訪問權的執行緒釋放這個資源為止。
這就是鎖定被呼叫函式的特性,即只能保證每次被乙個執行緒呼叫,執行緒優先順序高的呼叫的次數就多,低的就少,這就是所謂的強佔式。
下面讓我們看看mutex類的使用方法,以及與monitor和lock的區別。
將**修改如下:
private void thread1func()
}private void thread2func()
}private void testfunc(string str)
", str, system.datetime.now.millisecond.tostring());
thread.sleep(50);
}
執行結果如下:
可以看出,mutex只能互斥執行緒間的呼叫,但是不能互斥本執行緒的重複呼叫,即thread1中waitone()只對thread2中的waitone()起到互斥的作用,但是thread1並不受本wainone()的影響,可以呼叫多次,只是在呼叫結束後呼叫相同次數的releasemutex()就可以了。
那麼如何使執行緒按照呼叫順序來依次執行呢?其實把lock和mutex結合起來使用就可以了,改**如下:
private void thread1func()}}
private void thread2func()}}
前台鎖住**
這裡是你鎖的**
龍的傳人,龍的文化!
td>
C C 中的記憶體補齊機制
原文 在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別 如int long float等 的變數,也可以是一些復合資料型別 如陣列 結構 聯合等 的資料單元。在結構中,編譯器為結構的每個成員按其自然對界 alignment 條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲...
C C 中的記憶體補齊機制
在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別 如int long float等 的變數,也可以是一些復合資料型別 如陣列 結構 聯合等 的資料單元。在結構中,編譯器為結構的每個成員按其自然對界 alignment 條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第...
C C 中的記憶體補齊機制
今天做了道牛客的題,錯了。之前沒有接觸過記憶體補齊的問題。題目如下 在x86系統下,sizeof如下結構體的值是多少?12 345struct 答案是c 在c語言中,結構是一種復合資料型別,其構成元素既可以是基本資料型別 如int long float等 的變數,也可以是一些復合資料型別 如陣列 結...