首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在布尔值上使用比较和交换进行锁定

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

Stack Overflow用户
提问于 2015-03-29 19:15:01
回答 1查看 604关注 0票数 0

我正在试验atomic_compare_and_swap函数,以便对std::atomic<bool>执行基本锁。

我所期望的行为是,第二个线程,即Consume,将在while循环中的Access::get()开始时一直被阻塞,直到原子lock_被设置为true

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

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

我做错了什么?

我正在使用g++4.9 on Lubuntu

代码语言:javascript
复制
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;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-29 21:50:01

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

同时,你所施加的3秒延迟

代码语言:javascript
复制
this_thread::sleep_for(std::chrono::seconds(3));

main()仍然在滴答作响,当它过期时,使用者线程执行get(),而UNLOCKED_循环将首先看到UNLOCKED_false,但lock_是真的(因为它是由生产者设置的),因此它再次将UNLOCKED_的值更新为true和自旋。在CAS循环的下一次迭代中,它将看到lock_UNLOCKED_现在都是true (在上一次迭代中设置了UNLOCKED_),并且循环出现了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29333633

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档