2011-05-15 41 views
3

我設計了一個Stack包裝類。我的困惑是,如果我在彈出或推送對象到堆棧變量「ParameterStack」時使用lock。請讓我知道,這個類是否是線程安全的。我應該在下面的場景中使用鎖定

public static class StackManager 
{ 
    private static Stack ParameterStack = new Stack(); 

    public static T Pop<T>() 
    { 
     T RawObject; 
     T Result = default(T); 

     lock (ParameterStack) 
     { 
      RawObject = (T)ParameterStack.Pop(); 
     } 

     if (RawObject != null && RawObject is T) 
      Result = (T)RawObject; 

     return (T)Result; 
    } 

    public static void Push<T>(T Data) 
    { 
     lock (ParameterStack) 
     { 
      ParameterStack.Push(Data); 
     } 
    } 
} 

我已經創建了這個StackManager類用於學習目的。

回答

7

看起來沒問題。有一個(相當理論上的)論點,鎖定在ParameterStack本身並不完全安全,因爲你不擁有代碼。假設堆棧內某個地方有一個lock(this),你可能會陷入僵局。

public static class StackManager 
{ 
    private static Stack parameterStack = new Stack(); 
    private static object stackLock = new object(); 

    // now use lock(stackLock) instead of lock(ParameterStack) 

} 
1

你應該使用ConcurrentStack你的情況。 如果你不能夠使用ConcurrentStack - 您可以使用Stack.Synchronized()方法:

Stack mySynchronizedStack = Stack.Synchronized(myStack); 

但是,即使你使用Synchronized()方法枚舉仍然不是線程安全的,你應該使用鎖來枚舉你的籌碼。

Stack myStack = new Stack(); 
lock (myStack.SyncRoot) 
{ 
    foreach (var element in myStack) 
    { 
    } 
} 

不幸的是,但Stack通用版本沒有Synchonization()方法。 所以,你的代碼應該是:

public static class StackManager 
{ 
    private static Stack ParameterStack; 

    static StackManager() 
    { 
     ParameterStack = Stack.Synchronized(new Stack()); 
    } 

    public static T Pop<T>() 
    { 
     object RawObject = ParameterStack.Pop(); 

     return RawObject is T ? (T)RawObject : default(T); 
    } 

    public static void Push<T>(T Data) 
    { 
     ParameterStack.Push(Data); 
    } 
} 

,如果你想查詢的類型也應該使用object類型RawObject。在你的代碼中,如果你嘗試Pop不同類型的對象,你會得到一個異常。

+0

是的,但這需要Fx4,並不會履行'學習的目的' – 2011-05-15 07:22:24

+0

感謝您更新的代碼片段,如上所述,我將肯定會轉移到ConcurrentStack .NET Framework 4. – AbrahamJP 2011-05-15 07:55:59

1

是的,你應該。在C#中,默認情況下堆棧不同步。

1

是的,它是線程安全的。只要內部堆棧的任何使用位於一個鎖內,它就可以安全地用於多個線程。

你可以使用Stack<T>來避免所有的轉換。或者如oxilumin所說的,如果你不只是試圖學習如何製作線程安全的東西,那就使用ConcurrentStack。

+0

「您可以使用堆棧」 - 我認爲這個堆棧用於存放多種類型。看看這個名字。 – 2011-05-15 07:37:05

+0

好點。我可能不應該在我的早晨咖啡前回答問題;) – 2011-05-15 07:38:10

0

您是否知道ConcurrentStack類?這是一個高效的線程安全實現使用無鎖

相關問題