带锁的指令重新排序

时间:2016-09-29 06:21:20

标签: c++ multithreading

编译器会重新排序使用mutex保护的指令吗?我使用boolean变量来决定一个线程是否更新了某个结构。如果编译器重新排序指令,则可能会在更新结构的所有字段之前设置boolean变量。

struct A{
  int x;
  int y;
  // Many other variables, it is a big struct
}

std::mutex m_;
bool updated;
A* first_thread_copy_;
// a has been allocated memory

m_.lock();
first_thread_copy_->x = 1;
first_thread_copy_->y = 2;
// Other variables of the struct are updated here
updated = true;
m_.unlock();

在另一个线程中,我只检查结构是否已更新并交换指针。

while (!stop_running){

    if (updated){
        m_.lock();
        updated = false;
        A* tmp = second_thread_copy_; 
        second_thread_copy_ = first_thread_copy_;
        first_thread_copy_ = tmp;
        m.unlock();
     }
....
}

我的目标是尽可能快地保持第二个线程。如果它发现没有发生更新,它会继续并使用旧值来执行剩余的操作。

避免重新排序的一个解决方案是使用memory barriers,但我试图在mutex阻止内避免它。

2 个答案:

答案 0 :(得分:2)

您可以放心地假设锁定/解锁和锁定内的指令之间没有重新排序指令。解锁后或锁定前不会发生updated = true。两者都是障碍,并阻止重新排序。

你不能假设锁内的更新没有重新排序。 updated的更新可能发生在更新x或y之前。如果您的所有访问权限也处于锁定状态,那应该不是问题。

考虑到这一点,请注意,编译器不仅可能重新排序指令。 CPU也可能无序执行指令。

答案 1 :(得分:0)

这是什么锁定了gaurantee所以你不必使用updated。在旁注中,您应该锁定struct而非代码,并且每次访问a时都应该先锁定它。

struct A{
  int x;
  int y;
}

A a;
std::mutex m_;   //Share this lock amongst threads

m_.lock();
a.x = 1;
a.y = 2;
m_.unlock();

在第二个帖子上你可以做到

while(!stop)
{
  if(m_.try_lock()) {
    A* tmp = second_thread_copy_; 
    second_thread_copy_ = first_thread_copy_;
    first_thread_copy_ = tmp;
    m_.unlock();
  }
}

编辑:因为你覆盖了内部有互斥的结构是没有意义的。