我应该在以下场景中使用锁

时间:2011-05-15 07:18:11

标签: c# .net thread-safety

我设计了一个Stack包装类。我的困惑是,我应该在弹出或将对象推送到堆栈变量“lock”时使用ParameterStack。请告诉我这个类是否是线程安全的。

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类用于学习目的。

5 个答案:

答案 0 :(得分:7)

看起来不错。有一个(相当理论上)的论点,锁定ParameterStack本身并不完全安全,因为你没有代码。假设Stack中的某个地方有一个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 :(得分: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不同类型的对象,您将获得异常。

答案 2 :(得分:1)

是的,你应该。默认情况下,堆栈在C#中不会同步。

答案 3 :(得分:1)

是的,这是线程安全的。只要内部堆栈的任何使用都在锁定内,就可以安全地使用多个线程。

您可以使用Stack<T>来避免所有投射。或者正如oxilumin所说的那样,如果你不只是想学习如何制作线程安全的东西,请使用ConcurrentStack。

答案 4 :(得分:0)

您是否了解ConcurrentStack类?它是一个使用无锁

的高效线程安全实现