假設n的初始值為0, 在thread1在執行完ldc.i4.1後被thread2中斷(add指令並未執行),這時 thread2獲得的n的初始值仍然是0,假設thread2順利執行完,那麼這時n的值已經 是1了,當thread2執行完後,thread1繼續執行add指令,並且thread1也順利執行 完,這時,在thread1中的執行結果n仍然是1。因此,這也就出現了調用兩次n++ ,n仍然為1的情況。要解決這個問題的方法也很容易想到,就是讓上述四條IL語 句要不都不執行,要執行就都執行完,這有點事務處理的意思。
在C#中解 決這個問題的技術叫同步。同步的本質就是為某一個代碼塊加鎖,使其成為一個 整體,共同進退。最簡單的是使用lock為代碼塊加鎖。這個語句在前幾講已經多 次使用過了。lock語句可以鎖定任何的對象,如果鎖定的是類成員,直接使用 lock(obj)的形式即可,如果鎖定的是靜態成員,可以把鎖主在object類型上,代 碼如下:
lock(typeof(StaticClass))
{
... ...
}
對於Increment類,我們可以鎖定n++,也可以鎖定Inc 方法,如鎖定n++的Increment類的代碼如下:
class Increment
{
private int n = 0;
private int max;
private Object lockN = new Object();
public Increment(int max)
{
this.max = max;
}
public int result
{
get
{
return n;
}
set
{
n = value;
}
}
private void IncN()
{
lock (lockN)
{
n++;
}
}
public void Inc()
{
for (int i = 0; i < max; i++)
{
IncN();
}
}
}