【问题标题】:Synchronization between threads using Critical Section使用临界区的线程之间的同步
【发布时间】:2013-05-30 20:03:59
【问题描述】:
我有多个线程,ThreadA 和 ThreadsB-Z。
ThreadA 始终处于临界区,将数据从队列中弹出并通过套接字发送。
当从ThreadB 到ThreadZ 的任何线程要进入临界区时,它才希望ThreadA 离开临界区。然后它进入临界区,将一些数据推入队列并离开临界区。
我这里有两个问题:
- ThreadB-Z 怎么会(谁想进入临界区)
告诉 ThreadA 在需要时离开临界区
访问关键部分。
- 我试着用 SetEvent 或 PostThreadMessage 的想法来告诉
threadA 离开临界区,但我无法处理
自 ThreadA 不断弹出以来的任何事件或线程消息
使用 while(1) 将数据从队列中取出,并且没有消息循环或
WaitforSingleObject() 类型的东西来处理事件或线程消息
:(
我就像陷入了这种情况。欢迎任何帮助/建议。提前致谢。
【问题讨论】:
标签:
multithreading
events
synchronization
message
critical-section
【解决方案1】:
这里真正的问题是“ThreadA 总是在临界区”。 ThreadA 不应该无限期地锁定临界区。
在 C# 中,ThreadA 的代码如下所示:
Message message;
// Only lock critical section for the time it takes to modify the queue
lock(_messageQueueLock){
message = _messageQueue.Dequeue();
}
// do something with the message
在我看来,使用临界区时应遵守以下一般经验法则:
- 尽快进入和退出临界区(即尽量减少临界区中的代码量)。
- 使用临界区来保护资源/资产(例如共享内存、队列、列表等)
- 避免使用临界区来保护函数/方法调用。如果您从关键部分进行函数/方法调用...您正在增加创建死锁的可能性。
- 避免尝试从临界区中锁定临界区。否则可能会导致您的应用程序出现潜在的死锁。
- 避免在临界区尝试访问外部资源(例如执行数据库 SQL 查询)。
- 在有意义的情况下,我通常喜欢对关键部分使用以下命名约定:如果受保护的资产称为
messageQueue... 那么我将关键部分命名为 messageQueueLock
来自 Microsoft 的精彩引用:“当您使用任何类型的多线程时,您可能会将自己暴露在非常严重和复杂的错误中”[来源:MSDN]