mutex C ++很好用

时间:2015-04-10 10:02:37

标签: c++ multithreading boost mutex

我对互斥锁有些麻烦,请考虑这个例子:

boost::mutex m;


void thread1_unstack(std::stack<std::string>& msg) {

  while (true) {
    if (msg.empty()) continue;

    m.lock();
    std::string msg_string = msg.top();
    msg.pop();
    std::cout << msg_string << std::endl;  
    m.unlock();
  }
}

void thread2_stack(std::stack& msg) {
   while (1) {
      msg.push("very long message");  
   }
}

void wait_for_finish(std::stack& msg) {
   while (!msg.empty()) sleep(1);
}

int main() {
   std::stack<std::string> msg;

   boost::thread t1 = boost::thread(boost::bind(&thread1_unstack, boost::ref(msg));

   boost::thread t2 = boost::thread(boost::bind(&thread2_stack, boost::ref(msg));

   wait_for_finish(msg);

   t1.stop();
   t2.stop();
}

所以问题在于wait_for_finish函数。当调用msg.pop()时,函数检测到堆栈是空的,因此线程在juste之后被停止,有时,消息(std :: cout)没有完全打印在屏幕上。

所以我想&#34;锁定&#34; msg变量为3行:

    std::string msg_string = msg.top();
    msg.pop();
    std::cout << msg_string << std::endl;
像那样,wait_for_finish在std :: cout期间没有检测到堆栈是空的。

我试图锁定一个boost :: mutex并在最后解锁它,但没有任何改变。

所以我不知道如何解决它

2 个答案:

答案 0 :(得分:1)

您必须使用互斥锁保护所有访问权限:

boost::mutex m;


void thread1_unstack(std::stack<std::string>& msg) {

  while (true) {

    m.lock();
    bool msgEmpty = msg.empty();
    m.unlock();

    if (msgEmpty) continue;

    m.lock();
    std::string msg_string = msg.top();
    msg.pop();
    std::cout << msg_string << std::endl;  
    m.unlock();
  }
}

void thread2_stack(std::stack& msg) {
   while (1) {
      m.lock();
      msg.push("very long message");  
      m.unlock();
   }
}

void wait_for_finish(std::stack& msg) {

    while(true) {

        m.lock();
        bool msgEmpty = msg.empty();
        m.unlock();

        if(msgEmpty) break;
        sleep(1);
    }
}

int main() {
   std::stack<std::string> msg;

   boost::thread t1 = boost::thread(boost::bind(&thread1_unstack, boost::ref(msg));

   boost::thread t2 = boost::thread(boost::bind(&thread2_stack, boost::ref(msg));

   wait_for_finish(msg);

   t1.stop();
   t2.stop();
}

答案 1 :(得分:0)

我们的讨论中的评论显示您正在使用某种线程安全的可等待容器。你需要通过它的合作来停止线程,以确保它有时间完成它应该对最后一个对象做的任何工作。我会建议这种方法:

  1. 拥有一个stop标志,该标志是原子的或受互斥锁保护。它应该开始清除。

  2. 当线程从容器中获取对象时,在打印它之前,它会检查stop标志。如果设置了标志,则线程终止。

  3. 如果要停止线程,请设置stop标志,向容器添加虚拟对象,然后加入线程。

  4. 虚拟对象解除阻塞线程,并且它不会被打印,因为线程不会在设置stop标志的情况下打印。通过join线程,您可以确保它在您终止之前完成了它必须完成的所有工作。

    你也可以使用&#34;死亡对象&#34;做法。例如,假设您的代码无法排空空字符串 - 您可以使用空字符串作为死亡对象&#34;。它的工作原理如下:

    1. 当您从容器中获取对象时,请检查它是否为死亡对象。如果是,请终止。

    2. 要使线程终止,请将死亡对象排队,然后加入该线程。

    3. 这有相同的行为。对死亡对象进行排队会解除对线程的阻塞(因为容器不再是空的,只有在它被阻塞时才会阻塞),并保证线程在完成后终止(因为线程一旦将其取消就会检查)。加入线程可确保它在死亡对象之前完全处理完所有对象。