【发布时间】:2010-03-06 02:59:35
【问题描述】:
我有多个共享信号量的线程。线程 A 持有信号量(使用锁),线程 B 和 C 正在等待同一个信号量(也使用锁)。线程共享全局变量等。
在 C# 中有可以用来关闭线程 B 的技术吗?我可以在 A 中设置一个标志,让线程 B 检查该标志并在它控制信号量后立即退出,但我不知道有任何技术可以让线程 A 将信号量交给线程 B(并得到它当线程 B 退出时返回),没有线程 C 夺取控制权的风险。
有人对如何解决这个设计问题有任何建议吗?如果我处理不正确,我可以根据需要重写程序。
[编辑] 一位评论者指出我使用了错误的术语。评论者是正确的 - 我使用的是临界区,但鉴于一切都在单个进程中运行,在此示例中临界区在功能上等同于更通用的术语“信号量”。
[编辑] 有人询问更多细节,所以在这里。
可以有多个线程执行代码 A。只有一个线程执行代码 B。
代码 A:
private static Thread workerThread = null;
lock (lockObject)
{
... do some work ...
if (...condition...)
{
if (workerThread != null)
{
// Kill the worker thread and continue only after it is dead.
quitWorkerThread = true;
// Wait for the thread to die.
while (workerThread.IsAlive)
{
Thread.Sleep(50);
}
workerThread = null;
quitWorkerThread = false;
} // if (workerThread != null)
} // if (...condition...)
... do some more work ...
if (...condition...)
{
if (workerThread == null)
{
// Start the worker thread.
workerThread = new Thread(WorkerThread);
workerThread.Start();
} // if (workerThread == null)
} // if (...condition...)
... do even more work ...
} // lock (lockObject)
代码 B:
private void WorkerThread()
{
while (true)
{
if (quitWorkerThread)
{
return;
}
Thread.Sleep (2000);
if (quitWorkerThread)
{
return;
}
lock(lockObject)
{
if (quitWorkerThread)
{
return;
}
... do some work ...
} // lock(lockObject)
} // while (true)
} // WorkerThread
我怀疑我会使用 Aaron 解决方案的变体。我主要希望有一些更优雅的解决方案可用,但我怀疑就像这个项目的其他一切一样,这都是蛮力和极端情况:-(。
【问题讨论】:
-
“线程 A 持有信号量(使用锁)” -
lock语句是关键部分。您使用的是信号量还是临界区(锁)? -
如果你使用信号量,你可能会使用 waitOne()。
-
仅供参考,关键部分与信号量完全不同,即使在单个进程中也是如此。临界区恰好允许 一个 线程持有资源;一个信号量可能允许多个。锁定语义也不同;一个线程可以多次重新进入它自己的临界区,但是信号量并不关心线程标识,所以重新获取它太多次会死锁。对不起,迂腐,但区别非常重要。
-
感谢您的澄清,Aaronnaught。无需为迂腐道歉,这是计算机科学,魔鬼藏在细节中,一切都是魔鬼。
-
我认为术语差异存在于一般 comp sci 用法和 .NET 特定用法之间。在 .NET 中,
lock关键字等同于Monitor.Enter(lockObject);try{}finally {Monitor.Exit(lockObject);},因此与其说持有信号量,不如说是(获取然后)持有一个监视器或锁。在 .NET 中,“信号量”是指 Win32 事件句柄的特定托管包装器,它可以由多个单独的线程持有,这些线程等于在构造时指定的 int 值。然而,一般而言,CS“信号量”是“二进制”(如 .NET 监视器)或“计数”(如 .NET 信号量)。
标签: c# concurrency semaphore