几个小时后,我的头发被撕掉了,看来我被c ++ 11的unique_lock
的意外行为狠狠地殴打了。我一定有可怕的误会:
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#define N_THREADS 4
#define N_ITERATIONS 10000
#define N_LOOPS 1000000
class ThingMaJigger
{
public:
void fight() {
if(m.try_lock()) {
// more then one thread ends up here??!?!?
printf("I'm the winner!\n" );
m.unlock();
} else {
printf("Sleeping \n" );
}
}
private:
std::mutex m;
};
void worker(ThingMaJigger* ar,int tIdx)
{
ar->fight();
}
int main(int argc, char const *argv[])
{
for (int _loop = 0; _loop < N_LOOPS; ++_loop) {
std::vector<std::thread> ts;
ThingMaJigger t;
for (int i = 0; i < N_THREADS; ++i)
{
ts.emplace_back(worker,&t,i);
}
for (int i = 0; i < N_THREADS; ++i)
{
ts[i].join();
}
printf("\n");
}
return 0;
}
使用clang++ -std=c++11 -O2 -lpthread ./unique_lock.cpp
clang 3.7.0,g ++ 5.1.1,两者的行为方式相同。
I'm the winner!
Sleeping
Sleeping
I'm the winner!
I'm the winner!
Sleeping
I'm the winner!
Sleeping
I'm the winner!
I'm the winner!
Sleeping
Sleeping
Kinda看起来像多个工人持有相同的锁 与此同时,不是吗?
http://en.cppreference.com/w/cpp/thread/mutex/try_lock说:
返回值
如果成功获取锁定,则为true,否则为false。
注意:即使没有其他人,也允许try_lock
返回false
有锁。这不是什么意思。
答案 0 :(得分:3)
这是按预期工作的。
印刷后“我是胜利者”,你正在解锁。这使得其他线程也有机会获得它。
如果你只想要一个线程“赢”,你还应该有一个变量来表明某人是否还赢了。在创建线程之前将其设置为false。任何获取锁的线程都会成功检查该变量,以查看是否有其他人获胜。
bool somebodyWon = false; // make sure this is set to false before
// threads get created
if(m.try_lock()) {
if (somebodyWon) {
printf("Darn, someone beat me to it!\n");
} else {
printf("I'm the winner!\n");
somebodyWon = true;
}
m.unlock();
} else {
printf("I didn't even get a chance! \n" );
}
另一种方法,也是合法的,是从使用互斥锁转换为信号量,以便一个线程可以锁定对象,但让所有线程加入后父线程释放它。
答案 1 :(得分:0)
确信令人困惑。我们去购物吧!
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <unistd.h>
#define N_THREADS 4
#define N_ITERATIONS 10000
#define N_LOOPS 1000000
class ThingMaJigger
{
public:
void fight() {
if(m.try_lock()) {
// more then one thread ends up here??!?!?
printf("I'm the winner!\n");
usleep(1000000); // <<<< this.
// or can unlock() before other's try_lock()
m.unlock();
} else {
printf("Sleeping \n" );
}
}
private:
std::mutex m;
};
void worker(ThingMaJigger* ar,int tIdx)
{
ar->fight();
}
int main(int argc, char const *argv[])
{
for (int _loop = 0; _loop < N_LOOPS; ++_loop) {
std::vector<std::thread> ts;
ThingMaJigger t;
for (int i = 0; i < N_THREADS; ++i)
{
ts.emplace_back(worker,&t,i);
}
for (int i = 0; i < N_THREADS; ++i)
{
ts[i].join();
}
printf("\n");
}
return 0;
}