首页 文章

c#包含队列锁定的多线程

提问于
浏览
0

下面的代码是教授在课堂上提出的多线程示例 . 我是编码新手(第一门课程) . 我已阅读过多线程和使用锁 . 阅读理论很有趣 . var fun = Theory.Read(多线程);实际上编码线程和锁似乎让我感到困惑 .
试图理解下面代码中的两个线程将如何表现 . 从测试代码看起来看起来像lock1不会释放而message2没有被排队,但我可能错了 . 看起来存在同步问题 . 这是一个僵局的例子吗?我也想知道如果使用两个不同的队列,为什么需要锁和线程 . 我没有看到共享资源 . 有没有办法修复此代码以防止同步问题?

private static object Lock1 = new object(); // Protect MessageQueueOne
private static object Lock2 = new object(); // Protect MessageQueueTwo
private static Queue<string> MessageQueueOne = new Queue<string>();
private static Queue<string> MessageQueueTwo = new Queue<string>();

private static void AddMessages(string message1, string message2)
{
    lock (Lock1)
    {
        // (1) Thread 1 is here...
        MessageQueueOne.Enqueue(message1);

        lock (Lock2)
        {
            MessageQueueTwo.Enqueue(message2);
        }
    }
}

private static void RemoveMessages()
{
    lock (Lock2)
    {
        if (MessageQueueTwo.Count > 0)
        {
            // (2) Thread 2 is here...
            Console.WriteLine(MessageQueueTwo.Dequeue());
        }

        lock (Lock1)
        {
            if (MessageQueueOne.Count > 0)
            {
                Console.WriteLine(MessageQueueOne.Dequeue());
            }
        }
    }
}

private static void Main()
{
    Task taskOne = Task.Run(() =>
    {
        for (int i = 0; i < 100; ++i)
        {
            AddMessages($"Message One: {DateTime.Now}", $"Message Two: {DateTime.UtcNow}");

            Thread.Sleep(25);
        }
    });

    Task taskTwo = Task.Run(() =>
    {
        for (int i = 0; i < 100; ++i)
        {
            RemoveMessages();

            Thread.Sleep(25);
        }
    });

    taskOne.Wait();

    taskTwo.Wait();

    Console.Write("Tasks are finished");

    Console.ReadKey();
}

1 回答

  • 0

    帖子中的代码是死锁的经典示例,并且预计会在大多数情况下陷入僵局 . 请参阅Wikipedia有关死锁的文章中的更多链接 .

    导致死锁的原因是:一个线程锁定“lock1”并等待“lock2”,另一个线程同时锁定“lock2”并在获取“lock1”后将释放它,这将永远不会被等待线程释放 .

    标准解决方案

    • 听你的 class 知道答案

    • 阅读现有的例子

    • 如果上述失败 - 一个选项是以固定顺序获取资源(即,如果需要锁定多个资源,则首先获得"lock1",而不是"lock2"等等)以获取所有线程(Would you explain lock ordering?) .

相关问题