TPL任务和ReaderWriterLockSlim

时间:2014-08-31 13:24:13

标签: c# synchronization task-parallel-library readerwriterlockslim

我目前的项目中有一个奇怪的错误。这就是为什么我有两个问题:

1)为什么会发生这种情况? 2)我该如何解决这个问题?

其他一些信息:我在带有QuadCore CPU的系统上运行此功能(Intel Core2Quad Q9650)

我有一个可以从多个线程一次调用的函数“DoSomething()”:

public class SingletonClass    
{

    // Singleton
    public static SingletonClass Instance 
    {
        get { return _instance ?? (_instance = new SingletonClass()); }
    }

    private readonly ReaderWriterLockSlim _workLock = new ReaderWriterLockSlim();
    private bool _isWorkDone = false;

    // bool returns true for "Inner Task executed" and false for "Inner Task had been executed earlier"
    public bool DoSomething()
    {
        // workaround to fix: Thread.Sleep(50);
        _workLock.EnterWriteLock();
        try
        {
            if (!_isWorkDone)
            {
                Task.Factory.StartNew(DoWork());
                _isWorkDone = true;
                return true;
            }

            return false;
        }
        finally
        {
           _workLock.ExitWriteLock();
        }
    }
}

为了测试这个函数是否有效,我使用TPL来创建多个任务,几乎同时调用这个函数:

for (int i = 0; i < 10; i += 1)
{
    Task.Factory.StartNew(() =>
    {
        bool success = DoSomething();
        Console.WriteLine(success);
    });
}

我希望得到这样的输出:

  

true ,false,false,....

但我得到的是:

  

true,true,true,true ,false,false ....

记住:
1)为什么?
2)如何解决?

编辑:我添加了一个示例项目:[DELETED - 问题解决]

1 个答案:

答案 0 :(得分:0)

没办法,问题不在于锁定,而是在创建Singleton!

public static Dll Instance
{
    get { return _INSTANCE ?? (_INSTANCE = new Dll()); }
}

以上内容不受lock =&gt;保护你得到4个不同的实例!四种不同的锁!

private void CreateThreadsToAccess()
{
    Task[] tasks = new Task[10];
    for (int i = 0; i < tasks.Length; i += 1)
    {
        tasks[i] = Task.Factory.StartNew(() =>
        {
        //  here you get four different instances
            bool success = Dll.Instance.DoSomething();
            Console.WriteLine(success);
        });
    }

    Task.WaitAll(tasks);

    Console.WriteLine("Press any key to exit");
    Console.ReadKey();
}

如何纠正:

private static readonly object mylock = new object();
public static Dll Instance
{
    get 
    {
       if (_INSTANCE == null) 
       {
           lock (mylock) 
           {
              if (_INSTANCE == null) 
              {
                 _INSTANCE = new Dll();
              }
           }
       }
       return _INSTANCE;
    }
}