(轉)C# (線程安全的哈希表)Hashtable Synchronized vs SyncRoot

Synchronized vs SyncRoot 我們知道,在.net的一些集合類型中,譬如Hashtable和ArrayList,都有Synchronized靜態方法和SyncRoot實例方法,他們之間有聯繫嗎?我怎麼才能用好他們呢?
我們以Hashtable爲例,看看他們的基本用法:

Hashtable ht = Hashtable.Synchronized(new Hashtable());
lock (ht.SyncRoot)
{
//一些操作
}1,Synchronized表示返回一個線程安全的Hashtable,什麼樣的 hashtable纔是一個線程安全的呢?下邊我們就從.NET的源碼開始理解。
public static Hashtable Synchronized(Hashtable table)
{
if (table == null)
{
throw new ArgumentNullException("table");
}
return new SyncHashtable(table);
}
從源碼不難看出,Synchronized方法返回的其實是一個SynchHashtable類型的實例。在前邊我們說過,Synchronized表示返回一個線程安全的Hashtable,從這個解釋不難看出,SynchHashtable應該是繼承自Hashtable。下邊我們驗證一下。看看 SynchHashtable類型的源碼: Code
[Serializable]
private class SyncHashtable : Hashtable
{
// Fields
protected Hashtable _table;

// Methods
internal SyncHashtable(Hashtable table) : base(false)
{
this._table = table;
}

internal SyncHashtable(SerializationInfo info, StreamingContext context) : base(info, context)
{
this._table = (Hashtable) info.GetValue("ParentTable", typeof(Hashtable));
if (this._table == null)
{
throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
}
}

public override void Add(object key, object value)
{
lock (this._table.SyncRoot)
{
this._table.Add(key, value);
}
}

public override void Clear()
{
lock (this._table.SyncRoot)
{
this._table.Clear();
}
}

public override object Clone()
{
lock (this._table.SyncRoot)
{
return Hashtable.Synchronized((Hashtable) this._table.Clone());
}
}

public override bool Contains(object key)
{
return this._table.Contains(key);
}

public override bool ContainsKey(object key)
{
return this._table.ContainsKey(key);
}

public override bool ContainsValue(object key)
{
lock (this._table.SyncRoot)
{
return this._table.ContainsValue(key);
}
}

public override void CopyTo(Array array, int arrayIndex)
{
lock (this._table.SyncRoot)
{
this._table.CopyTo(array, arrayIndex);
}
}

public override IDictionaryEnumerator GetEnumerator()
{
return this._table.GetEnumerator();
}

public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null)
{
throw new ArgumentNullException("info");
}
info.AddValue("ParentTable", this._table, typeof(Hashtable));
}

public override void OnDeserialization(object sender)
{
}

public override void Remove(object key)
{
lock (this._table.SyncRoot)
{
this._table.Remove(key);
}
}

internal override KeyValuePairs[] ToKeyValuePairsArray()
{
return this._table.ToKeyValuePairsArray();
}

// Properties
public override int Count
{
get
{
return this._table.Count;
}
}

public override bool IsFixedSize
{
get
{
return this._table.IsFixedSize;
}
}

public override bool IsReadOnly
{
get
{
return this._table.IsReadOnly;
}
}

public override bool IsSynchronized
{
get
{
return true;
}
}

public override object this[object key]
{
get
{
return this._table[key];
}
set
{
lock (this._table.SyncRoot)
{
this._table[key] = value;
}
}
}

public override ICollection Keys
{
get
{
lock (this._table.SyncRoot)
{
return this._table.Keys;
}
}
}

public override object SyncRoot
{
get
{
return this._table.SyncRoot;
}
}

public override ICollection Values
{
get
{
lock (this._table.SyncRoot)
{
return this._table.Values;
}
}
}
}


Collapse Methods

呵呵,果然不出我們所料,SyncHashtable果然繼承自Hashtable,SyncHashtable之所有能實現線程的安全操作,就是因爲在他們的一些方法中,就加了lock,我們知道,哪一個線程執行了lock操作,在他還沒有釋放lock之前,其他線程都要處於堵塞狀態。 SyncHashtable就是通過這種方法,來實現所謂的線程安全。

現在我們理解了Synchronized的含義和用法,那接下來我們看看他和SyncRoot之間的關係。
SyncRoot表示獲取可用於同步 Hashtable 訪問的對象,老實說,這個解釋不好理解,要想真正理解他的用法,我們還得從源碼開始: public virtual object SyncRoot
{
get
{
if (this._syncRoot == null)
{
Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
}
return this._syncRoot;
}
}


如果您清楚Interlocked的用法,這段代碼沒什麼難理解的了(不清楚的朋友找GOOGLE吧),Interlocked爲多個線程共享的變量提供原子操作。原子操作就是單線程操作。在一個Hashtable實例中,不論我們在代碼的任何位置調用,返回的都是同一個object類型的對象。我們在開始寫的 lock(ht.SyncRoot)和下邊的操作作用是一樣的.
static object obj = new object();
lock(obj)
{
// 一些操作
}
他們之間不同的是,我們聲明的static object類型對象是類型級別的,而SyncRoot是對象級別的。

通過上面的分析,我們都應該能理解Synchronized 和 SyncRoot用法,他們之間的關係就是:
Hashtable 通過Synchronized方法,生成一個SynchHashtable類型的對象,在這個對象的一個方法中,通過lock (this._table.SyncRoot)這樣的代碼來實現線程安全的操作,其中this._table.SyncRoot返回的就是一個 object類型的對象,在一個SynchHashtable對象實例中,不管我們調用多少次,他是唯一的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章