使用比较和交换布尔值进行锁定

时间:2015-03-29 19:15:02

标签: c++11 atomic compare-and-swap

我正在尝试atomic_compare_and_swap函数对std::atomic<bool>进行基本锁定。

我期待的行为是第二​​个线程,即Consumewhile循环中始终被Access::get()保持阻塞状态lock_设置为true

由于sleeps我已经介绍了它始终是第一个线程Produce将原子设置为true以防止第二个线程继续进行。

不幸的是情况并非如此,我可以看到第二个线程立即执行,并且根本不会被阻止。

我做错了什么?

我正在使用g++4.9 on Lubuntu

class Access
{
  atomic<bool> lock_;
  bool         UNLOCKED_;

public:
  Access() : lock_(false), UNLOCKED_(false){}

  void set()
  {
    // lock
    while(!atomic_compare_exchange_strong(&lock_, &UNLOCKED_, true)) {}                 
    this_thread::sleep_for(std::chrono::seconds(20));      
    cout << "set" << endl;   
  }

  void get()
  {
    // lock
    while(!atomic_compare_exchange_strong(&lock_, &UNLOCKED_, true)){} 
    cout << "get" << endl;        
  }
};

Access gTest; // global

void Produce() { gTest.set(); }

void Consume() { gTest.get(); }

int main() {
  thread producer(Produce);
  this_thread::sleep_for(std::chrono::seconds(3));
  thread consumer(Consume);
  producer.join();
  consumer.join();
  return 0;
}

1 个答案:

答案 0 :(得分:2)

当生产者线程执行set()和CAS循环时,它会看到UNLOCKED_lock_的值相同(false),设置{{ 1}}为true,返回true。因此,循环退出,此线程等待20秒。

与此同时,你用

施加了3秒的延迟
lock_
在main()中的

仍然在滴答作响,当它到期时,消费者线程执行this_thread::sleep_for(std::chrono::seconds(3)); 并且CAS循环将首先看到get()UNLOCKED_但是false是true(因为它是由生产者设置的),因此它将lock_的值更新为UNLOCKED_并再次旋转。在CAS循环的下一次迭代中,它将看到truelock_现在都是UNLOCKED_(在前一次迭代中设置了true),并且循环中断出。