-1

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

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);
    });
}

我希望得到这样的输出:

,假,假,……

但我得到的是:

真、真、真、真、假、假……

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

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

4

1 回答 1

0

没办法,问题不在于锁,而在于单例的创建!

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

以上不受锁的保护=>你得到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;
    }
}
于 2014-08-31T14:42:05.407 回答