用C ++提升 - 好奇的互斥行为

时间:2015-06-23 15:44:37

标签: c++ multithreading boost boost-thread boost-mutex

我正在尝试Boost个线程,因为据我所知,我可以编写一个多线程Boost应用程序并在Windows或Linux中编译它,而pthreads,我更熟悉,严格用于* NIX系统。

我有以下示例应用程序which is borrowed from another SO question

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <iostream>

#define NAP_DURATION    (10000UL)   // 10ms

boost::mutex io_mutex;

void count(int id)
{
    for (int i = 0; i < 1000; ++i)
    {
        boost::mutex::scoped_lock lock(io_mutex);
        std::cout << "Thread ID:" << id << ": " << i << std::endl;
        if (id == 1)
        {
            std::cout << "I'm thread " << id << " and I'm taking a short nap" << std::endl;
            usleep(NAP_DURATION);
        }
        else
        {
            std::cout << "I'm thread " << id << ", I drink 100 cups of coffee and don't need a nap" << std::endl;
        }
        std::cout << "Thread ID:" << id << ": " << i << std::endl;
        boost::thread::yield();
    }
}

int main(int argc, char* argv[])
{
    boost::thread thrd1( boost::bind(&count, 1));
    boost::thread thrd2( boost::bind(&count, 2));

    thrd1.join();
    thrd2.join();
    return 0;
}

我通过以下方式在我的Ubuntu 14.04 LTS系统上安装了Boost:

sudo apt-get install libboost-all-dev

我通过以下代码编译上面的代码:

g++ test.cpp -lboost_system -lboost_thread -I"$BOOST_INLCUDE" -L"$BOOST_LIB"

我遇到了一些看似有些不一致的问题。如果我设置一个冗长的NAP_DURATION,比如1秒(1000000),似乎只有线程1才能获得互斥锁,直到它完成其操作,并且线程{{1}非常罕见永远获得锁,直到线程2完成,即使我将1设置为仅几毫秒。

当我使用NAP_DURATION编写类似的此类应用程序时,锁定通常会在线程之间或多或少地随机交替,因为另一个线程已经在互斥锁上被阻止。

所以,对于问题:

  1. 这是预期的行为吗?
  2. 有没有办法控制这种行为,例如使作用域锁定的行为像锁定操作一样排队?
  3. 如果(2)的答案是“否”,是否可以实现与pthreads条件变量类似的东西,而不必担心锁定/解锁呼叫失败?
  4. Boost是否可以解锁?我正在使用RAII方法而不是手动锁定/解锁,因为显然解锁操作可能会失败并抛出异常,而我正在尝试使此代码稳固。
  5. 谢谢。

    澄清

    我知道将调用线程置于休眠状态不会解锁互斥锁,因为它仍然在范围内,但预期的调度顺序如下:

    • Thread1锁定,获取互斥锁。
    • Thread2锁定,阻止。
    • Thread1执行,释放锁定,并立即再次尝试锁定。
    • Thread2已经在等待锁定,在thread1之前获取它。

2 个答案:

答案 0 :(得分:5)

  

这是预期的行为吗?

是和否。您不应该对哪个线程获得互斥锁有任何期望,因为它未指定。但它肯定在预期的行为范围内。

  

是否有办法控制此行为,例如使作用域锁定的行为类似于锁定操作排队?

不要这样使用互斥锁。只是不要。仅使用互斥锁,使其相对于线程正在执行的其他操作保持非常短的时间。

  

如果(2)的答案是&#34; no&#34;,是否可以使用Boost条件变量实现类似的操作,而不必担心锁定/解锁调用失败?

不确定。编码你想要的。

  

scoped_locks保证解锁吗?我使用RAII方法而不是手动锁定/解锁,因为显然解锁操作可能会失败并引发异常,我试图使此代码稳固。

目前尚不清楚您对此感到担忧,但建议使用RAII方法。

答案 1 :(得分:1)

你为什么感到惊讶? 如果你期望线程2在线程1处于睡眠状态时获取互斥锁,那么,是的,这是预期的行为并且你的理解是错误的,因为你的锁在范围内。

但是如果你因为在循环迭代结束时线程1和线程2之间缺少交替而感到惊讶,那么你可以看一下this SO question关于调度的看法&#34;不公平&#34;