在 2 种方法中同步 2 个互斥锁

Synchronization of 2 Mutex in 2 methods

提问人:Yurii Salyha 提问时间:10/25/2023 最后编辑:Yurii Salyha 更新时间:10/26/2023 访问量:45

问:

我有 2 种方法 TIC 和 TAC,它们只输出“TIC”或“TAC”。我的目标是创建多个 TIC 和 TAC 线程之后。 最终结果应为: TIC TAC TIC TAC TIC TAC

在这里,我创建线程。

Class1 a = new ();

Thread thread1 = new Thread(() => a.TIC());
Thread thread2 = new Thread(() => a.TIC());
Thread thread3 = new Thread(() => a.TIC());

Thread thread4 = new Thread(() => a.TAC());
Thread thread5 = new Thread(() => a.TAC());
Thread thread6 = new Thread(() => a.TAC());

thread3.Start();
thread5.Start();
thread2.Start();
thread6.Start();
thread4.Start();
thread1.Start();

thread1.Join();
thread2.Join();
thread3.Join();
thread4.Join();
thread5.Join();
thread6.Join();

这里是TIC和TAC方法

public class Class1
{
    public Mutex mutexTIC = new Mutex(true);
    public Mutex mutexTAC = new Mutex(false);

    public void TIC()
    {
        mutexTIC.WaitOne();
        Console.WriteLine("TIC");

        mutexTAC.ReleaseMutex();
    }

    public void TAC()
    {
        mutexTAC.WaitOne();
        Console.WriteLine("TAC");
        mutexTIC.ReleaseMutex();
    }
}

我还尝试添加锁,添加互斥锁作为参数,尝试使用事件。 但是每次我收到这个System.ApplicationException时:“对象同步方法从未同步的代码块调用。我不知道如何修复它。 对于任何不清楚之处,我深表歉意。希望我解释得足够多。

C# .NET 互斥 锁线程同步

评论

0赞 Theodor Zoulias 10/25/2023
为什么你以这种奇怪的顺序开始线程,而不是像你那样从 1 到 6?Join
0赞 Theodor Zoulias 10/25/2023
您是否有兴趣知道为什么会出现这些异常,或者您想知道如何生成特定的 TIC/TAC 模式?在第二种情况下,您能否在所有 6 个线程完成后编辑问题并包含程序的理想输出?ApplicationException
1赞 Yurii Salyha 10/26/2023
@reply,我以奇怪的顺序启动线程,以确保我的代码在任何情况下都能正常工作。实际上,我都很好奇为什么我会得到这个异常,我想知道如何产生它

答:

1赞 Anton Tykhyy 10/25/2023 #1

您收到此异常是因为您使用不正确:您正在创建主线程,但随后尝试在另一个线程上释放它。之所以存在此限制,是因为包装了一个操作系统内核互斥锁对象,该对象(至少在 Windows 上)强制执行这些线程规则。 和 relatives 也包装内核同步对象,并具有类似的限制。但是,在托管程序中,几乎从不需要使用这些旧对象(例外情况是需要它们与其他进程或非托管代码同步)。而不是 ,使用具有较少限制性规则的托管同步对象,例如:MutexmutexTICClass1MutexManualResetEventMutexSemaphoreSlim

// in Class1:
public SemaphoreSlim mutexTIC = new (1, 1);
public SemaphoreSlim mutexTAC = new (0, 1);

public void TIC()
{
    mutexTIC.Wait();
    Console.WriteLine("TIC");

    mutexTAC.Release();
}

public void TAC()
{
    mutexTAC.Wait();
    Console.WriteLine("TAC");
    mutexTIC.Release();
}

请注意,此代码可以作为玩具示例,但是如果执行了一些可能引发异常的非平凡操作,则需要非常小心地处理异常和错误,以免泄漏信号量计数并创建死锁。TIC()TAC()