開發的系統有這樣一個功能:產生單據號碼。我的做法是查看數據表中單據號碼欄位當前值,在此基礎上加1生成新的單據號碼並存儲。原本沒有想太多,但是我們老大看了後,跟我說,如果有兩個用戶同時訪問到這個單據號碼,那麼新產生的號碼對於數據表來說是重複的,怎麼辦?
這就涉及一個多用戶訪問共享資源的問題。如果該資源是隻讀的,沒有問題,但是如果每個用戶都可以對其更新操作,就會出現數據同步的問題。說到這裏,想起來,上學的時候學習數據庫就學過的銀行取款的問題,記得當時的解決方案是加鎖,當然今天要解決這個問題依然是加鎖。
如果究其原因,可以知道,實際上這裏涉及的是一個線程同步的問題(多用戶實際上對服務器來說就是多線程的訪問),msdn中對線程同步的講述和解決方案解釋的很詳細。系統中關於共享訪問資源(數據)的代碼爲關鍵代碼,如果要實現同步,必須在一個線程訪問的時候,對這段代碼加鎖控制。等這個線程訪問完畢,釋放鎖,允許第二個線程的訪問,以此類推。
方案有很多,今天先闡述經常用到的:monitor, lock關鍵字
測試代碼:
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace Demo1
{
class safeThread
{
private static object obj=new object(); //注意:這裏設置的對象,最好是private,protected,不能public,否則容易出現問題
static void Main()
{
Thread thread = new Thread(new ThreadStart(foo));
thread.Name = "my thread";
thread.Start();
Thread thread2 = new Thread(new ThreadStart(foo));
thread2.Name = "my thread 2";
thread2.Start();
Thread thread3 = new Thread(new ThreadStart(foo));
thread3.Name = "my thread 3";
thread3.Start();
}
private static void foo()
{
Monitor.Enter(obj);
{
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine("Thead executinged");
}
Monitor.Exit(obj); //測試的時候把此句註釋掉,即可看到lock的效果
}
}
}
{
lock(obj);
{
//關鍵代碼區域
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine("Thead executinged");
}
}