【问题标题】:C++ (CAS-like) synchronization on getter and setter of user defined types用户定义类型的 getter 和 setter 上的 C++(类似 CAS)同步
【发布时间】:2013-10-08 04:29:10
【问题描述】:

假设有一个用户定义的类MyClass,它有一个setter 和一个getter 函数。

class MyClass {
    int m_value;
    public:
        void set(int value)
        { m_value = value; }

        int get() const
        { return m_value;}
};

还有一个函数increment()可以将对象的值加1,可以在多个线程中调用。

void increment(MyClass& myClass)
{
    myClass.set(myClass.get() + 1);
}

使这个函数线程安全的最好方法是什么?只使用锁?有什么办法可以通过一些类似 CAS 的操作来实现吗?

【问题讨论】:

  • 你不太可能需要原子,它们甚至可能更慢,最好用互斥锁来保护类的数据。
  • 你当然可以添加 myClass::increment() 方法。

标签: c++ multithreading locking lock-free


【解决方案1】:

如果您使用的是 C++11,您可以只使用std::atomic<int>,它提供原子loadstoreincrement,这似乎是您需要的一切。

我怀疑您不需要原子,尽管在大多数情况下它们会比您的基本互斥锁慢。

在您做出决定之前,请查看其他 question

【讨论】:

  • 我不认为std::atomic<int> 会起作用,因为我使用的是用户定义的类型。感谢您的建议和链接。
  • 所以你唯一的解决方案就是用互斥锁来保护它。简化决策;)
  • 我的意思是在你的 MyClass 内部使用 std::atomic。如果这就是您所说的用户定义类型。
  • @user571470 如果值是原子的,他们就不能这样做。递增操作是有序的。不安全的是您的 Increment 函数。您应该提供增加值的方法,而无需读取,然后写入。
  • coliru.stacked-crooked.com/a/e0aa11350d653bb2 这两者都没有数据竞争,但根据您使用它们的方式,它们可能在逻辑上不正确。这就是使类线程安全的困难。
【解决方案2】:

使用 std::mutex 并享受

    #include <mutex>

    class MyClass 
    {
        int m_value;
        std::mutex mtx;

        void set(int value) 
        {
            mtx.lock();
            m_value = value;
            mtx.unlock();
        }

        int get() const 
        {
            return m_value;
        }
    } 

【讨论】:

  • 这行不通。 increment() 仍然不是线程安全的。
  • increment() 不需要线程安全,因为 MyClass.set 函数是线程安全的。
  • 但是两个线程可以用相同的值调用set(),这不是两次递增值的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 2015-11-01
相关资源
最近更新 更多