在C++11
中,std::atomic_flag
对线程循环很有用:
static std::atomic_flag s_done(ATOMIC_FLAG_INIT);
void ThreadMain() {
while (s_done.test_and_set()) { // returns current value of s_done and sets to true
// do some stuff in a thread
}
}
// Later:
s_done.clear(); // Sets s_done to false so the thread loop will drop out
ATOMIC_FLAG_INIT
将标志设置为false
,这意味着线程永远不会进入循环。 (坏)解决方案可能会这样做:
void ThreadMain() {
// Sets the flag to true but erases a possible false
// which is bad as we may get into a deadlock
s_done.test_and_set();
while (s_done.test_and_set()) {
// do some stuff in a thread
}
}
std::atomic_flag
的默认构造函数指定该标志将处于未指定状态。
我可以将atomic_flag
初始化为true
吗?这是atomic_flag
的正确用法吗?
答案 0 :(得分:4)
在启动主题之前,您始终可以调用test_and_set
。
答案 1 :(得分:2)
您错误地使用atomic_flag
来实现自旋锁。正确的形式是:
static std::atomic_flag s_done(ATOMIC_FLAG_INIT);
void ThreadMain() {
while (s_done.test_and_set()) { // returns current value of s_done and sets to true
// spin while s_done is held by another thread
}
// do some stuff in a thread
// Later:
s_done.clear(); // Sets s_done to false so the thread loop will drop out
虽然我建议使用RAII支架,但您可以return
或throw
功能正常,锁定将自动释放。
ATOMIC_FLAG_INIT
是false
,因为atomic_flag
的值通常被解释为指示某个资源是否由线程独占。在程序启动时,没有这样的线程,实际上相关的资源甚至可能没有被初始化。因此false
将是适当的初始值。
至于初始化为true
,标准不保证甚至可以为atomic_flag
分配布尔值。
答案 2 :(得分:2)
未使用ATOMIC_FLAG_INIT
(或{0})初始化的原子标志处于不确定状态。
你可以做些什么来解决你的问题:
std::atomic_flag lock = ATOMIC_FLAG_INIT;
现在获得锁定:
while (lock.test_and_set(std::memory_order_acquire))
; // ...
然后释放它:
lock.clear(std::memory_order_release);
这就是所谓的spin-lock
。