[英]Is it possible to make atomic operations on singleton object thread safe automatically
我有 singleton object 在两个在单独线程上运行的单元之间共享。 例如,
线程 A Singleton.getInstace().incCounter();
线程 B Singleton.getInstance().decCounter();
是否可以将这个原子实现为线程安全的,而不用打扰消费者以线程安全的方式进行操作。
就像是
static Singleton& GetInstance() {
std::scoped_lock lock(m_mtx);
static Singleton* singleton = new Singleton();
return *singleton;
}
我想这不会起作用,因为锁将在返回后被释放,但 incCounter 和 decCounter 将在没有锁的情况下被调用。 是否有可能在原子操作完成之前保持锁处于活动状态。 在 incCounter 和 decCounter 内进行锁定是这里唯一的解决方案或在单元 A 和单元 B 中的唯一解决方案。
当前的锁什么也没做。 C++ 标准要求在一个线程中初始化static
函数局部变量。 也就是说,编译器将确保在其初始化时不会出现竞争条件。 所以锁可以防止一些不可能发生的事情。
您需要在递增/递减函数中加锁。 他们需要锁定同一个互斥锁。 虽然也许他们可以增加/减少一个原子变量,在这种情况下你根本不需要锁。
您可以(但可能不应该)创建一个新类型LockedSingleton
,它存储对 singleton和std::unique_lock
的引用。 这将是您的GetInstance()
返回的内容。 LockedSingleton
需要有自己的递增/递减函数,它转发到其内部 singleton 参考,以及任何其他接口函数。
class LockedSingleton
{
private:
std::unique_lock<std::mutex> lock_;
Singleton &obj_;
private: //Only friends can construct. Also, non-copyable.
LockedSingleton(std::mutex &mtx, Singleton &obj)
: lock_(mtx)
, obj_(obj)
{}
friend Singleton& GetInstance();
public:
void incCounter() {obj.incCounter();}
void decCounter() {obj.decCounter();}
};
static LockedSingleton GetInstance() {
static Singleton* singleton = new Singleton();
return LockedSingleton(m_mtx, *singleton);
}
请注意,这仅适用于 C++17 及更高版本,由于保证省略,因为LockedSingleton
是不可复制的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.