2017-08-25 36 views
1

我目前正在学习条件变量,我开始明白了。但是从here代码:为什么在不使用std :: unique_lock的时候这里声明了

void print_id (int id) { 
    std::unique_lock<std::mutex> lck(mtx); 
    while (!ready) cv.wait(lck); 
    // ... 
    std::cout << "thread " << id << '\n'; 
} 

void go() { 
    std::unique_lock<std::mutex> lck(mtx); <<<<<< ? 
    ready = true; 
    cv.notify_all(); 
} 

print_id我理解,因为它会被cv.wait()使用的lck声明。在go函数中,我不明白lck的用途声明,因为它没有被使用。我试图删除和运行,似乎很好。是真的有必要还是我错过了什么?

+2

http://en.cppreference.com/w/cpp/thread/condition_variable也许这更清晰。 “lck不被使用” - 但只是构造它有一个非常重要的副作用:它锁定mtx。 – Mat

+0

感谢您的评论。我需要重新检查我的学习材料。如果我记得,lock_guard会自动锁定mtx。但是在unique_lock上,需要手动调用锁定方法来锁定mtx。即使在http://en.cppreference.com/w/cpp/thread/unique_lock/unique_lock上,它也表示它并未锁定构建中的互斥锁。 –

+2

@newbieprogrammerz看看你正在使用的过载3,它会锁定互斥锁。 – NathanOliver

回答

5

当你

std::unique_lock<std::mutex> lck(mtx); 

您创建一个名为lckmtx调用lock的对象。你需要这个,因为ready是一个非原子变量,并且在没有同步的情况下写入它是未定义的行为,因为你有另一个线程正在读取它。一旦go结束lck被销毁,它会自动为您调用unlock

锁定警卫通常不被“使用”。我们使用它们,以便我们可以锁定互斥锁,而无需担心在每个可能的退出路径中解锁互斥锁。为了让生活更轻松,我们将解锁代码放入一个对象的析构函数中,该对象将在函数的任何退出路径上销毁,以便互斥锁始终处于解锁状态。

+0

感谢您的有用解释。似乎最好使用unique_lock而不是lock_guards。无论如何,这可能是主题,但只是为了丰富,是否有办法使变量原子,而不使用锁。也许使用volatile修饰符?感谢您回答我的问题 –

+1

@newbieprogrammerz您可以使用['std :: atomic'](http://en.cppreference.com/w/cpp/atomic/atomic) – NathanOliver

+0

我会研究一下。非常感谢。祝你有美好的一天! –

相关问题