使用boost :: lock_guard进行线程饥饿

时间:2013-12-25 21:36:16

标签: c++ multithreading boost

我正在尝试学习boost库并且正在通过boost :: thread的示例。

以下示例说明了 boost :: lock_guard 对线程同步的使用,确保对 std :: cout 的访问不是并发的:

#include <boost/thread.hpp>
#include <boost/format.hpp>
#include <iostream>

void wait(const int secs) {
    boost::this_thread::sleep(boost::posix_time::seconds(secs));
}

boost::mutex mutex;

void thread1() {
    for (int i = 0; i < 10; ++i) {
        wait(1); // <-- all works fine if wait is placed here
        boost::lock_guard<boost::mutex> lock(mutex);
        std::cout << boost::format("thread A here %d\n") % i ;
    }
}

void thread2() {
    for (int i = 0; i < 10; ++i) {
        wait(1); //  <-- all works fine if wait is placed here
        boost::lock_guard<boost::mutex> lock(mutex);
        std::cout << boost::format("thread B here %d\n") % i;
    }

}

int main() {
    boost::thread t1(thread1);
    boost::thread t2(thread2);
    t1.join();
    t2.join();
}

结果几乎是人们所期望的结果,即通过打印的两个线程交替发送消息:

thread A here 0
thread B here 0
thread A here 1
thread B here 1
thread A here 2
thread B here 2
thread A here 3
thread B here 3
thread A here 4
thread B here 4
...

然而,一个小小的修改 - 将等待电话移到锁定守卫的范围内 - 导致了一个惊喜:

void thread1() {
    for (int i = 0; i < 10; ++i) {
        boost::lock_guard<boost::mutex> lock(mutex);
        wait(1); // <== !
        std::cout << boost::format("thread A here %d\n") % i ;
    }
}

void thread2() {
    for (int i = 0; i < 10; ++i) {
        boost::lock_guard<boost::mutex> lock(mutex);
        wait(1);  // <== !
        std::cout << boost::format("thread B here %d\n") % i;
    }

现在,thead1或thread2赢得互斥锁的初始“竞争”,然后在每次循环迭代时反复获胜,从而使另一个线程挨饿!

示例输出:

thread B here 0
thread B here 1
thread B here 2
thread B here 3
thread B here 4
thread B here 5
thread B here 6
thread B here 7
thread B here 8
thread B here 9
thread A here 0
thread A here 1
thread A here 2
thread A here 3
thread A here 4
thread A here 5
thread A here 6
thread A here 7
thread A here 8
thread A here 9

任何人都可以解释为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

这是因为在获取锁之后,等待调用导致第二个线程开始执行。由于第二个线程无法获取锁定,因此它将进入等待状态,直到锁定可用。在您的情况下,锁定在第一个线程完成循环之前不可用。

相关问题