【问题标题】:Thread suspends itself and another one resumes it afterwards - sometimes second event happens first线程暂停自己,然后另一个线程恢复它 - 有时第二个事件首先发生
【发布时间】:2012-05-22 03:52:49
【问题描述】:

我有两个线程;线程 2 为线程 1 提供了必要的数据,并且可以开始处理与线程 1 并行处理的另一块数据,但如果线程 1 较慢(是的,我知道“线程 1读取线程 2 同时写入的内容”,我有两个缓冲区形式的保护,而不是一个)。代码如下:

Thread 1:
while(!shouldexit)
{
    // some code
    Thread1_Ready = true;
    SuspendThread (Thread1_Handle);
}

Thread 2:
while(!shouldexit)
{
    while(!Thread1_Ready)
    {
        // do nothing
    }
    // some other code
    ResumeThread(Thread1_Handle);
}

问题是,有时线程 2 中的整个代码比线程 1 中的SuspendThread 发生得更快。结果是线程 1 保持挂起状态,直到线程 2 的另一个循环通过。这会导致线程 1 没有处理一条数据(不是很好,但在我的应用程序中可以接受),而且更严重的是,当停止按钮触发 shouldexit = true 时,线程 1 只是无限期地处于挂起模式。

我想到的两种可能的解决方案也不起作用: 1 - 将Thread1_Ready = true; 放在SuspendThread(Thread1_Handle); 之后(显然,代码Thread1_Ready = true; 永远不会执行) 2 - 将线程 1 中的 SuspendThread(Thread1_Handle); 行放在线程 2 的开头,就在 // some other code 之前,但这会导致线程 1 重新进入主循环的延迟,这将是非常不可预测的。

这种情况可以用不同的方式解决吗?

【问题讨论】:

  • 忙着等待不是解决这个问题的正确方法。了解如何使用正确的同步原语。

标签: multithreading parallel-processing synchronization


【解决方案1】:

你有一个经典的producer-consumer problem。标准(在 99% 的情况下足够)解决方案是互斥保护队列。在您的情况下,队列大小为 1,但队列语义仍然适用。

这将解决您的问题,因为示例运行如下所示:

Thread 1: Lock queue, see that queue is empty, wait for queue full signal
Thread 2: Produce data
Thread 2: Lock queue, push data into queue (has now size 1), Unlock queue and wake up Thread 1
Thread 2: Produce data
Thread 2: Lock queue, see that queue is full, wait for queue space signal
Thread 1: Wakes up, gets data, sends queue space signal

【讨论】:

  • 谢谢,看了文章,好像很好理解。但是有一个问题 - 获取/释放互斥锁是一种原子操作吗?因为否则我需要一种方法来确保线程不会同时进入临界区(队列操作)。
  • @fynjyzn:互斥锁是一种保证原子操作的机制,所以是的,从获取到释放互斥锁的顺序是原子的。由于您使用的是 C++,您可能想看看 Boost.Thread 及其条件变量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-21
相关资源
最近更新 更多