C# 多线程同步
我正在做一个需要多线程同步的程序。以下是我的方法:
private void RunSimulation()
{
int sideSize = (int)Math.Ceiling((double)_simulationField.GetLength(0) / (double)MAX_SECTOR_SIZE);
int threadsCount = sideSize * sideSize;
sync = new bool[threadsCount + 1];
for (int i = 0; i < sync.Length; i++)
{
sync[i] = false;
}
for (int sector = 0; sector <= threadsCount; sector++)
{
Thread sectorThread = new Thread(DoSector);
sectorThread.IsBackground = true;
sectorThread.Start(sector);
}
}
并且:
private void DoSector(object obj)
{
int sector = (int)obj;
Library.Pair sectorPosition = GetSectorPosition(sector);
while (true)
{
for (int i = sectorPosition.X; i < sectorPosition.X + MAX_SECTOR_SIZE && i < _simulationField.GetLength(0); i++)
{
for (int j = sectorPosition.Y; j < sectorPosition.Y + MAX_SECTOR_SIZE && j < _simulationField.GetLength(1); j++)
{
if (_simulationField[i, j] != null)
{
MoveCreature(_simulationField[i, j], i, j);
}
}
}
sync[sector] = true;
while (sync.Contains(false) && sector != sync.Length)
{
Thread.Sleep(10);
}
if (sector == sync.Length)
{
for (int i = 0; i < sync.Length; i++)
{
sync[i] = true;
}
}
Thread.Sleep(500);
}
}
所以您可以看到我正在使用数组进行同步。但我在徘徊这是一个好方法吗?这里的操作sync.Contains的复杂度为O(n)并且它在循环中......有没有更好的方法来进行同步?
I'm doing one program which needs multithreading synchronization. Here are my methods:
private void RunSimulation()
{
int sideSize = (int)Math.Ceiling((double)_simulationField.GetLength(0) / (double)MAX_SECTOR_SIZE);
int threadsCount = sideSize * sideSize;
sync = new bool[threadsCount + 1];
for (int i = 0; i < sync.Length; i++)
{
sync[i] = false;
}
for (int sector = 0; sector <= threadsCount; sector++)
{
Thread sectorThread = new Thread(DoSector);
sectorThread.IsBackground = true;
sectorThread.Start(sector);
}
}
And:
private void DoSector(object obj)
{
int sector = (int)obj;
Library.Pair sectorPosition = GetSectorPosition(sector);
while (true)
{
for (int i = sectorPosition.X; i < sectorPosition.X + MAX_SECTOR_SIZE && i < _simulationField.GetLength(0); i++)
{
for (int j = sectorPosition.Y; j < sectorPosition.Y + MAX_SECTOR_SIZE && j < _simulationField.GetLength(1); j++)
{
if (_simulationField[i, j] != null)
{
MoveCreature(_simulationField[i, j], i, j);
}
}
}
sync[sector] = true;
while (sync.Contains(false) && sector != sync.Length)
{
Thread.Sleep(10);
}
if (sector == sync.Length)
{
for (int i = 0; i < sync.Length; i++)
{
sync[i] = true;
}
}
Thread.Sleep(500);
}
}
So you can see that I'm using an array for the synchronization. But I'm wandering is it good way to do this? Here the operation sync.Contains is with complexity O(n) and it's in loop...Is there a better way to do the synchronization?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为您想在此处使用 Barrier 。它是一个允许线程分阶段执行的同步对象。所有线程必须在一个阶段完成其计算,然后才能执行下一阶段。这正是您所需要的。
I think you want to use a Barrier here. It's a synchronization object that allows threads to execute in phases. All threads must finish their computation in one phase before they are allowed to execute the next one. This is just what you need.
使用数组进行同步不是线程安全的,但单独使用“sync.Contains(false)”则不是。
如果两个线程同时运行sync.Contains(false)并且都返回false怎么办?
另外,我看到你的 ThreadCount 是 sideSize 的平方。创建大量线程是非常低效的。你拥有的线程越多,你拥有的上下文切换就越多。一次上下文切换大约需要 8000 个时钟周期。此外,创建一个线程大约需要 100,000 个时钟周期,并且每个线程必须有自己的堆栈,默认情况下约为 4MB。
您想要的是与核心一样多的线程,以及从队列中提取并处理其工作的每个线程。
您可能最好使用线程池,但我也看到您的线程处于一段时间(true),这意味着它们永远不会结束。线程池不适用于长时间运行的线程。
总的来说,我认为你的设计需要一些改进。既然您似乎正在学习,我会推荐一种允许使用线程池的设计,而不是 while(true) 循环。
其他人也许能为您提供适合您的已知设计模式的“名称”,但我不知道设计模式的名称。
Using an array to sync is not thread safe, yet alone "sync.Contains(false)".
What if two threads are running sync.Contains(false) at the same time and both come back false?
Also, I see your ThreadCount is sideSize squared. It is very inefficient to create lots of threads. the more threads you have, the more context switches you have. A context switch is about 8000 clock cycles. Also, creating a thread costs about 100,000 clock cycles and each thread must have its own stack which is about 4MB by default.
What you want is about as many threads as cores and each thread to pull from a queue and process its work.
You're probably best off using the thread pool, but I also see your threads are in a while(true), which means they never end. The thread pool isn't meant for long running threads.
Over all, I think your design needs some work. Since you seem to be learning, I would recommend a design that allows the use of the thread pool, instead of while(true) loops.
Someone else might be able to give you a "name" for a known design pattern that would work for you, but I'm not up on names for designs patterns.