C++ 无锁同步

C++ 无锁同步,c++,c,multithreading,gcc,C++,C,Multithreading,Gcc,我正在考虑使用下面的机制来同步两个或更多线程。我认为唯一的缺点是CPU的使用。请分享您对该机制的评论。这个实现有什么问题吗?(假设gcc的_sync*功能是可移植的) 因此,任何想要访问共享或全局数据的线程都会首先调用acquireLock,访问全局数据,然后释放锁。您正在实现一种自旋锁。您可以使用CAS循环代替递增和递减: void acquireLock () { while (!_sync_bool_compare_and_swap(&lock, 0, 1)) {} }

我正在考虑使用下面的机制来同步两个或更多线程。我认为唯一的缺点是CPU的使用。请分享您对该机制的评论。这个实现有什么问题吗?(假设gcc的_sync*功能是可移植的)


因此,任何想要访问共享或全局数据的线程都会首先调用acquireLock,访问全局数据,然后释放锁。

您正在实现一种自旋锁。您可以使用CAS循环代替递增和递减:

void acquireLock () {
    while (!_sync_bool_compare_and_swap(&lock, 0, 1)) {}
}

void releaseLock () {
    int unlock_success = _sync_bool_compare_and_swap(&lock, 1, 0);
    assert(unlock_success);
}
比较和交换将检查变量内容是否与预期值(第二个参数)匹配。如果是,它将把变量设置为新值(第三个参数)。如果预期值不匹配,则调用失败。这是一个原子操作。

什么是好的解决方案。但是,既然您也问了您的解决方案可能有什么问题,我的看法是:

您将“锁获取失败”分为两个步骤:

  • 尝试获取锁(增加标志)
  • 如果备份失败(减少标志)
  • 因此,即使线程无法获取锁,它仍然会修改全局状态(增量),只是在以后的某个时间修复此修改。问题在于,无法保证“修复”会立即、很快或根本不会发生。增量和减量本身是原子的,但不是一对

    基本上,如果某个线程试图获取锁并失败,那么它可能无法立即减少计数器(线程可以被调出)。现在,即使当前锁持有者释放锁,其他线程也无法再获取锁,因为该值将始终大于1(也就是说,直到“sleep”重新打开并执行减量)。这要么造成瓶颈(所有线程依赖于所有“失败”线程执行递减),要么造成死锁(如果“失败”线程因任何原因递增并死亡)

    这不会发生在@jxh的解决方案中,因为锁获取(无论是失败还是成功)作为一个整体是一个原子步骤

    void acquireLock () {
        while (!_sync_bool_compare_and_swap(&lock, 0, 1)) {}
    }
    
    void releaseLock () {
        int unlock_success = _sync_bool_compare_and_swap(&lock, 1, 0);
        assert(unlock_success);
    }