前一篇文章介紹了什么是單例模式以及如何使用單例模式。那么在多線程程序中我們如何使用單例模式呢?也就是說在多線程中我們如何保證類實例的唯一性?
眾所周知,多線程中使用較多的是鎖lock。
lock是確保一個線程位於代碼的臨界區時,另一個線程不進入臨界區。如果其他的線程試圖進入鎖定的代碼,將一直等待(被阻止)直到該對象被釋放。
程序運行時創建一個靜態只讀的線程輔助對象:
public static readonly object syncroot=new object();
在同一時刻加鎖的那部分代碼只能被一個線程訪問:
lock(syncroot)
{
if(instance==null)
{
instance=new singleton();
}
}
上面的代碼每次進行調用時都需要加鎖lock,對性能有一定影響。可以先判斷實例是否存在,不存在再加鎖lock。
if(instance==null)
{
lock(syncroot)
{
if(instance==null)
{
instance=new objec();
}
}
}
上面的代碼中,對實例是否為空我們進行了兩次判斷,為什么呢?
當實例instance==null時,兩個線程同時調用上面的代碼,第一重條件都符合可以進入。此時由於lock機制,只能一個線程進入,另一個線程等候。這里如果沒有第二重是否為null條件判斷,第一個線程執行實例化對象退出后,第二個線程進入會再一次實例化對象。這樣就沒有達到我們單實例的目的。