我有一个函数f1,它包含一个简单的循环,它通过布尔标志控制。该标志不会写入f1内部。
我有另一个清除旗帜的功能。
在不同的线程上调用这两个函数。
如果在进入f1循环之前锁定互斥锁,则f2将无法获取它以清除标记。
如果在进入f1中的循环之前我没有锁定互斥锁,则该标志不受保护。这是否重要,因为该函数只能读取它?
我的问题是我是否需要在进入f1循环之前保护标志,因为它只是被读取?如果是这样,怎么样?
如果只将标志写入一个地方,我是否还需要互斥锁?
我错过了一些基本的东西吗?
TIA
class X
{
public:
X() :
m_thread(),
m_isDone(false),
m_mutex()
{
m_thread = std::unique_ptr<std::thread>(new std::thread( [=]{ run(); } ));
}
~X()
{
// tell the thread to exit
m_isDone = true;
// wait for the thread to terminate
m_thread->join();
}
void f1()
{
// locking the mutex will prevent f2 from clearing the flag
std::lock_guard<std::mutex> lock(m_mutex);
while (!m_isDone)
{
// do some stuff
}
}
void f2()
{
// lock the mutex
std::lock_guard<std::mutex> lock(m_mutex);
m_isDone = true;
}
private:
std::unique_ptr<std::thread> m_thread;
bool m_isDone;
mutable std::mutex m_mutex;
};
答案 0 :(得分:1)
只需改变:
bool m_isDone;
为:
std::atomic<bool> m_isDone;
这将使您对m_isDone
的读取和写入保证原子(您需要执行此操作,因为它在不同的线程中被读取和写入)。 atomic
也不需要任何类型的互斥锁,锁等。
请注意,在您的解决方案中,f1
持有锁永久,因此无论如何f2
永远无法获取它。带锁的正确解决方案更复杂,更不必要:
bool isDone() { // easily replaced by atomic load
std::lock_guard<std::mutex> lock(m_mutex);
return m_isDone;
}
void f1() {
while (!isDone()) {
// stuff
}
}