gpt4 book ai didi

c# - C#中自制线程池的多线程死锁

转载 作者:太空宇宙 更新时间:2023-11-03 12:50:14 29 4
gpt4 key购买 nike

对于我在这里发布这么长的代码,我深表歉意,但我没有其他方法可以帮助您重现我的问题。我给你的代码当然是我正在使用的代码的缩影。我知道我可以使用 QueueUserWorkItem 直到最近我还在使用它,但我意识到我的线程太短以至于我的 ThreadDispatcher 方法在第一个完成。所以我想看看这种方式是否更快。问题是我遇到了僵局,我真的不明白为什么。我正在发布您可以直接编译和重现问题的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace TestWhatever
{
public class Program
{
static MyClass ThisClass = new MyClass();
static void Main()
{
ThisClass.Start();
for (int Cnt = 0; Cnt < 5; Cnt++)
{
Console.WriteLine("Launching Frame " + Cnt);
ThisClass.Update();//Frames loop
}
}
}

public class MyClass
{
Random MyRandom = new Random();

public static object _MultiDispatcherLocker = new object();
public static bool MonoDispacherThreadLocked = true;
public static bool MultiDispacherThreadLocked = true;
// Thread pool in multithreading case
private int MaxThreadsInParallel = 5;
private static int MaxNumOfPool = 20;
private Thread[] ThreadsPool;
public static object _ThreadLockerList;
private Func<string>[] ThreadFunctions;
public bool[] ThreadLockedBools = Enumerable.Repeat(true, MaxNumOfPool).ToArray();


public void Start()
{
StartThreads();
}

public void Update()
{

lock (_MultiDispatcherLocker)
{
MultiDispacherThreadLocked = false;
Monitor.Pulse(_MultiDispatcherLocker);
}
Thread.Sleep(1000);
}

private void StartThreads()
{
ThreadsPool = new Thread[MaxNumOfPool];
_ThreadLockerList = new object();
ThreadFunctions = new Func<string>[MaxNumOfPool];
ThreadLockedBools = new bool[MaxNumOfPool];

for (int Cnt = 0; Cnt < MaxNumOfPool; Cnt++)
{
Console.WriteLine("Preparing ThreadID: " + Cnt);
ThreadLockedBools[Cnt] = true;
ThreadsPool[Cnt] = new Thread(new ParameterizedThreadStart(LaunchThread));
ThreadsPool[Cnt].Start(Cnt);
}

Thread ThreadedMainThread = new Thread(new ThreadStart(ThreadDispatcher));
ThreadedMainThread.Start();
ThreadedMainThread.Priority = System.Threading.ThreadPriority.Highest;
}

private void LaunchThread(object iThreadID)
{
int ThreadID = (int)iThreadID;
lock (_ThreadLockerList)
{
while (ThreadLockedBools[ThreadID])
Monitor.Wait(_ThreadLockerList);
}
while (true)
{
Console.WriteLine("Starting ThreadID: " + ThreadID);
ThreadFunctions[ThreadID]();
Console.WriteLine("Ending ThreadID: " + ThreadID);
lock (_MultiDispatcherLocker)
{
ThreadLockedBools[ThreadID] = true;
MultiDispacherThreadLocked = false;
Monitor.Pulse(_MultiDispatcherLocker);
}
lock (_ThreadLockerList)
{
Console.WriteLine("Blocking ThreadID: " + ThreadID);
while (ThreadLockedBools[ThreadID])
Monitor.Wait(_ThreadLockerList);
}
}
}


private void ThreadDispatcher()//object Obj)
{
lock (_MultiDispatcherLocker)
{
while (MultiDispacherThreadLocked)
Monitor.Wait(_MultiDispatcherLocker);
}
while (true)
{

for (int Cnt = 0; Cnt < 20; Cnt++)//Threads loop
{

if (RunningThreads() < MaxThreadsInParallel)
{
int CurrIntTest = MyRandom.Next(100000, 10000000);

int ThreadID = GetNextEmptyThread();


ThreadFunctions[ThreadID] = () => { MyMethodInThread(CurrIntTest); return null; };
lock (_ThreadLockerList)
{
ThreadLockedBools[ThreadID] = false;
Monitor.Pulse(_ThreadLockerList);
}
}
else//wait until someone ends
{
lock (_MultiDispatcherLocker)
{
while (MultiDispacherThreadLocked)
{
Monitor.Wait(_MultiDispatcherLocker);
}
}
}
}

lock (_MultiDispatcherLocker)
{
MultiDispacherThreadLocked = true;
while (MultiDispacherThreadLocked)
Monitor.Wait(_MultiDispatcherLocker);
}
}
}

private void MyMethodInThread(int Counter)
{
List<string> MyDummy = new List<string>();
for (int Cnt = 0; Cnt < Counter; Cnt++) MyDummy.Add("Dummy");
}

private int RunningThreads()
{
int ToReturn = 0;
for (int Cnt = 0; Cnt < MaxThreadsInParallel; Cnt++)
{
if (!ThreadLockedBools[Cnt] || ThreadsPool[Cnt].ThreadState != System.Threading.ThreadState.WaitSleepJoin)
ToReturn++;
}
return ToReturn;
}

private int GetNextEmptyThread()
{
for (int Cnt = 0; Cnt < MaxThreadsInParallel; Cnt++)
{
if (ThreadLockedBools[Cnt] && ThreadsPool[Cnt].ThreadState == System.Threading.ThreadState.WaitSleepJoin)
return Cnt;
}
return -1;
}

}
}

如果你能帮我解决这个问题,那就太棒了。

最佳答案

让我们看看你有什么。

LaunchThread(线程):

lock (_ThreadLockerList)
{
while (ThreadLockedBools[ThreadID])
Monitor.Wait(_ThreadLockerList);
}

ThreadDispatcher(线程):

lock (_ThreadLockerList)
{
ThreadLockedBools[ThreadID] = false;
Monitor.Pulse(_ThreadLockerList);
}

Monitor.Pulse调用释放的线程不一定是ThreadLockedBools[ThreadID] = false的线程,此时会立即进入 Monitor.Wait 再次,从而有效地吃信号。

要解决这个问题(通常在这种情况下),请使用 Monitor.PulseAll相反。

关于c# - C#中自制线程池的多线程死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35819187/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com