在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
当多人同时操作时有可能会出现一些意外情况,我们可以应用lock关键词,lock是将语句块标示为临界区,确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其它线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。 以下以订单号做一个实验。 Table表結構如下:
Table表結構
ifobject_id('tb') isnotnulldroptable tb
createtable tb(PONo nvarchar(10) ,CreateBy nvarchar(20) ,CreateDate smalldatetime) go select*from tb go --PONo CreateBy CreateDate ------------ -------------------- ----------------------- --(0 个数据列受到影响) 前台代码如下:
前臺代碼如下
protectedvoid Button1_Click(object sender, EventArgs e)
{ string name = User.Identity.Name.ToString(); string PONo = TestFactory.GetPONumber(name); Response.Write(PONo); } 后臺代碼如下,未使用lock:
后臺代碼,未使用lock:
publicclass TestFactory
{ privatestaticobject objPONo =newobject(); publicstaticstring GetPONumber(string name) { //lock (objPONo) //{ //定義訂單號PONo string PONo =string.Empty; //將訂單號PONo自動加1 string strsql ="update tb set PONo=PONo+1,CreateBy='"+ name +"',CreateDate=getdate()"; int i = SQLHelper.ExecuteNonQuery(strsql); //如果登陸人為Takako,線程睡眠3秒.以作測試 if (name.ToLower() =="takako_yang") { Thread.Sleep(3000); } //如果update失敗,表示DB中不存在資料,則往DB塞入第一筆訂單號PONo:1000000000. if (i ==0) { strsql ="insert into tb values(1000000000,'"+ name +"',getdate())"; i = SQLHelper.ExecuteNonQuery(strsql); } //選出最后一筆 strsql ="select max(PONo) from tb"; object o = SQLHelper.ExecuteScalar(strsql); if (o == DBNull.Value) { PONo ="1000000000"; } else { PONo = SQLHelper.ExecuteScalar(strsql).ToString(); } return PONo; //} } } 实验者路人甲、路人乙,在程序中添加了一段Thread.Sleep(3000),判断当实验者为甲时,睡眠3秒再继续后面的动作。 当甲按下甲页面上的按钮,乙在1秒后也按下乙页面上按钮; 这时乙页面会往DB塞一笔订单号PONo:1000000000; 3秒后,甲页面也会往系统塞一笔订单号PONo:1000000000; 很显然,出现了两笔一模一样的订单号,这不是我们想要的。
后台代码,使用lock后:
后臺代碼,使用lock后:
publicclass TestFactory
{ privatestaticobject objPONo =newobject(); publicstaticstring GetPONumber(string name) { lock (objPONo) { //定義訂單號PONo string PONo =string.Empty; //將訂單號PONo自動加1 string strsql ="update tb set PONo=PONo+1,CreateBy='"+ name +"',CreateDate=getdate()"; int i = SQLHelper.ExecuteNonQuery(strsql); //如果登陸人為Takako,線程睡眠3秒.以作測試 if (name.ToLower() =="takako_yang") { Thread.Sleep(3000); } //如果update失敗,表示DB中不存在資料,則往DB塞入第一筆訂單號PONo:1000000000. if (i ==0) { strsql ="insert into tb values(1000000000,'"+ name +"',getdate())"; i = SQLHelper.ExecuteNonQuery(strsql); } //選出最后一筆 strsql ="select max(PONo) from tb"; object o = SQLHelper.ExecuteScalar(strsql); if (o == DBNull.Value) { PONo ="1000000000"; } else { PONo = SQLHelper.ExecuteScalar(strsql).ToString(); } return PONo; } } } 將DB中的資料刪光,delete tb 和上一個實驗一樣,甲按下甲頁面按鈕后,乙在1秒后也按下乙頁面按鈕. 結果如下:甲頁面在3秒后顯示了订单号PONo:1000000000;乙在3秒后顯示了訂單號PONo:1000000001。 這正是理想的結果。 |
请发表评论