简体   繁体   English

用 std::atomic 实现的 shared_lock

[英]shared_lock implemented with std::atomic

I can't afford to hold shared_lock due to its weight.由于它的重量,我不能持有 shared_lock 。 Instead I implemented what I think is shared_lock but with atomic value.相反,我实现了我认为是 shared_lock 但具有原子价值的东西。 Will this code work, or have I missed something?这段代码会起作用,还是我错过了什么?

update: I added RAII classes around atomic mutex.更新:我在原子互斥体周围添加了 RAII 类。

namespace atm {
static const unsigned int g_unlocked = 0;
static const unsigned int g_exclusive = std::numeric_limits<unsigned int>::max();
using mutex_type = std::atomic<unsigned int>;

class exclusive_lock {
  public:
    exclusive_lock(mutex_type& mutex) : _mutex(mutex) {
      unsigned int expected = g_unlocked;
      while (!_mutex.compare_exchange_weak(expected, g_exclusive)) {
        _mm_pause();
        expected = g_unlocked;
      }
    }
    ~exclusive_lock() { _mutex.store(g_unlocked, std::memory_order_release); }
  private:
    mutex_type& _mutex;
};

class shared_lock {
  public:
    shared_lock(mutex_type& mutex) : _mutex(mutex) {
      unsigned int expected = _mutex;
      while (expected == g_exclusive || !_mutex.compare_exchange_weak(expected, expected + 1)) {
        _mm_pause();
        expected = _mutex;
      }
    }
    ~shared_lock() {  _mutex.fetch_sub(1, std::memory_order_release); }
  private:
    mutex_type& _mutex;
};
} // namespace atm

For correctness I think this looks reasonable, I don't see a problem.为了正确起见,我认为这看起来很合理,我认为没有问题。 I might have missed something, but a seq_cst CAS is more than sufficient for acquiring a lock.我可能错过了一些东西,但是 seq_cst CAS 足以获得锁。 It looks like you're avoiding integer wrap-around by using the max value as something special.看起来你通过使用最大值作为特殊的东西来避免 integer 环绕。

The mutex=0 unlock only needs to be release , not seq_cst . mutex=0解锁只需要release ,而不是seq_cst (Same for the -=1 shared unlock, but that won't make it more efficient on x86, only on weakly-ordered ISAs). (与-=1共享解锁相同,但这不会使其在 x86 上更有效,仅在弱排序 ISA 上)。 Also, compare_exchange_weak would be totally fine;另外, compare_exchange_weak完全没问题; you're retrying in a loop anyway so spurious failure is not different from a failed compare.无论如何,您都在循环重试,因此虚假失败与失败的比较没有什么不同。

If you're on x86, you'd normally want _mm_pause() inside your spin loop, and possibly some kind of backoff to reduce contention if multiple threads are all trying to acquire the lock at once.如果您使用的是 x86,您通常希望在自旋循环中使用_mm_pause() ,并且如果多个线程都试图同时获取锁,则可能需要某种退避来减少争用。

And usually you want to spin read-only until you see the lock available, not keep hammering with atomic RMWs.而且通常您希望以只读方式旋转,直到您看到可用的锁,而不是继续使用原子 RMW。 (See Does cmpxchg write destination cache line on failure? If not, is it better than xchg for spinlock? ). (请参阅是否 cmpxchg 在失败时写入目标缓存行?如果不是,它是否比 xchg 用于自旋锁更好? )。

Also, short is a strange choice;此外, short是一个奇怪的选择。 if any size is going to perform worse than int, it's often short.如果任何大小的性能比 int 差,它通常很短。 But probably it's fine, and ok I guess if that helps it pack into the same cache line as the data you're modifying.但可能没问题,好吧,我想这是否有助于将它打包到与您正在修改的数据相同的缓存行中。 (Although that cache line will be the victim of false sharing contention from other threads hammering on it trying to take the lock.) (尽管该缓存行将成为其他线程试图获取锁的虚假共享争用的受害者。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 何时在 std::shared_lock 上使用 defer_lock? - When to use defer_lock on std::shared_lock? 错误:使用ReaderLock = std :: shared_lock的&#39;shared_mutex&#39;不是&#39;std&#39;的成员 <std::shared_mutex> ; - error: ‘shared_mutex’ is not a member of ‘std’ using ReaderLock = std::shared_lock<std::shared_mutex>; 同一线程中的 std::unique_lock 和 std::shared_lock - 不应该工作,但是可以吗? - std::unique_lock and std::shared_lock in same thread - shouldn't work, but does? 带有std :: shared_lock的std :: shared_mutex是读者还是作家更喜欢? - std::shared_mutex with std::shared_lock is reader or writer preferring? 我可以在 std::shared_mutex 上使用 std::shared_lock 更改数据吗? - Can I change data with a std::shared_lock on a std::shared_mutex? 将boost :: shared_lock升级为独占锁 - Upgrading boost::shared_lock to exclusive lock Boost Shared_lock / Unique_lock,给作者优先权? - Boost Shared_lock / Unique_lock, giving the writer priority? 将 shared_lock 升级为独特的锁使用、时序和设计 - Upgrade shared_lock to unique lock usage, timing and design 根据条件创建 shared_lock 或 unique_lock - Create shared_lock or unique_lock based on a condition 错误:没有匹配函数调用&#39;boost :: shared_lock <boost::shared_mutex> :: shared_lock(const Lock&)&#39; - error: no matching function for call to 'boost::shared_lock<boost::shared_mutex>::shared_lock(const Lock&)'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM