一旦可用就获得锁定

eno*_*ram 5 c++ concurrency mutex boost-thread

我有两个线程试图锁定相同的boost::mutex.其中一个线程是连续处理一些数据,另一个是周期性地显示当前状态.根据我的意图,处理线程非常频繁地释放锁并重新获取它,以便显示线程可以在需要时接入并获取它.所以,显然,我希望显示线程在下一次由进程线程释放时获取锁.但是,它没有这样做,相反,它等待锁定并且仅在来自进程线程的许多锁定释放循环之后获取它.

请检查说明我的问题的最小例子:

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

using namespace std;
using namespace boost;

mutex mut;

void process() {
        double start = time(0);
        while(1) {
                unique_lock<mutex> lock(mut);
                this_thread::sleep(posix_time::milliseconds(10));
                std::cout<<".";
                if(time(0)>start+10) break;
        }
}

int main() {

        thread t(process);

        while(!t.timed_join(posix_time::seconds(1))) {
                posix_time::ptime mst1 = posix_time::microsec_clock::local_time();
                cout<<endl<<"attempting to lock"<<endl;
                cout.flush();

                unique_lock<mutex> lock(mut);

                posix_time::ptime mst2 = posix_time::microsec_clock::local_time();
                posix_time::time_duration msdiff = mst2 - mst1;
                cout << std::endl<<"acquired lock in: "<<msdiff.total_milliseconds() << endl;
                cout.flush();
        }

}
Run Code Online (Sandbox Code Playgroud)

编译: g++ mutextest.cpp -lboost_thread -pthread

当我运行可执行文件时,示例输出如下所示:

...................................................................................................
attempting to lock
....................................................................................................................................................................................................................................................................................................................................................................................................................................
acquired lock in: 4243
...................................................................................................
attempting to lock
........................................................................................................
acquired lock in: 1049
...................................................................................................
attempting to lock
........................................................................................................................
acquired lock in: 1211
....................................
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在最坏的情况下,显示线程在捕获锁定之前等待424个锁定释放周期.

我显然是以错误的方式使用互斥锁,但解决这个问题的常用方法是什么?

eno*_*ram 0

我已经按照 Dale Wilson 和 FKaria 的建议使用条件解决了这个问题,但我在相反的方向上使用了它。因此,进程线程检查暂停标志,当它被设置时,它会等待条件,从而释放锁。显示线程控制暂停标志,它还通过条件通知它来恢复进程线程。代码:(代码大部分相同,我用 标记了新行//New

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

using namespace std;
using namespace boost;

mutex mut;
condition cond;

volatile bool shouldPause = false; //New

void process() {
        double start = time(0);
        while(1) {
                unique_lock<mutex> lock(mut);

                if(shouldPause) cond.wait(mut); //New

                this_thread::sleep(posix_time::milliseconds(10));
                std::cout<<".";
                if(time(0)>start+10) break;
        }
}

int main() {

        thread t(process);

        while(!t.timed_join(posix_time::seconds(1))) {
                posix_time::ptime mst1 = posix_time::microsec_clock::local_time();
                cout<<endl<<"attempting to lock"<<endl;
                cout.flush();
                shouldPause = true; // New
                unique_lock<mutex> lock(mut);

                posix_time::ptime mst2 = posix_time::microsec_clock::local_time();
                posix_time::time_duration msdiff = mst2 - mst1;
                cout << std::endl<<"acquired lock in: "<<msdiff.total_milliseconds() << endl;
                cout.flush();

                shouldPause = false; // New
                cond.notify_all(); // New
        }

}
Run Code Online (Sandbox Code Playgroud)

现在的输出正是我想要的:

...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 8
...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 8
...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 9
...................................................................................................
attempting to lock
.
acquired lock in: 8
...................................................................................................
attempting to lock
.
acquired lock in: 9
..........................
Run Code Online (Sandbox Code Playgroud)