[英]Is it possible to make atomic operations on singleton object thread safe automatically
I have singleton object shared between two units operating on seperate threads.我有 singleton object 在两个在单独线程上运行的单元之间共享。 For example,
例如,
Thread A Singleton.getInstace().incCounter();线程 A Singleton.getInstace().incCounter();
Thread B Singleton.getInstance().decCounter();线程 B Singleton.getInstance().decCounter();
Is it possible to implement this atomics to be thread safe without bothering the consumers to do it in thread safe way.是否可以将这个原子实现为线程安全的,而不用打扰消费者以线程安全的方式进行操作。
Something like就像是
static Singleton& GetInstance() {
std::scoped_lock lock(m_mtx);
static Singleton* singleton = new Singleton();
return *singleton;
}
I guess this will not work as the lock will be released after the return but incCounter and decCounter will be called without the lock.我想这不会起作用,因为锁将在返回后被释放,但 incCounter 和 decCounter 将在没有锁的情况下被调用。 Is it somehow possible to keep the lock active till atomic operation is completed.
是否有可能在原子操作完成之前保持锁处于活动状态。 Is doing a lock within the incCounter and decCounter the only solution here or in unit A and unit B only solution.
在 incCounter 和 decCounter 内进行锁定是这里唯一的解决方案或在单元 A 和单元 B 中的唯一解决方案。
The current lock accomplishes nothing.当前的锁什么也没做。 A
static
function-local variable is required by the C++ standard to be initialized in exactly one thread. C++ 标准要求在一个线程中初始化
static
函数局部变量。 That is, the compiler will ensure that there can be no race conditions on its initialization.也就是说,编译器将确保在其初始化时不会出现竞争条件。 So the lock is protecting against something that can't happen.
所以锁可以防止一些不可能发生的事情。
You need to put a lock in the increment/decrement functions.您需要在递增/递减函数中加锁。 And they need to lock the same mutex.
他们需要锁定同一个互斥锁。 Though perhaps they could increment/decrement an atomic variable, in which case you don't need a lock at all.
虽然也许他们可以增加/减少一个原子变量,在这种情况下你根本不需要锁。
You could (but probably shouldn't) create a new type LockedSingleton
which stores a reference to the singleton and a std::unique_lock
.您可以(但可能不应该)创建一个新类型
LockedSingleton
,它存储对 singleton和std::unique_lock
的引用。 This would be what your GetInstance()
returns.这将是您的
GetInstance()
返回的内容。 LockedSingleton
would need to have its own increment/decrement functions which it forwards to its internal singleton reference, as well as any other interface functions. 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);
}
Note that this only works in C++17 and above, due to guaranteed elision, since LockedSingleton
is non-copyable.请注意,这仅适用于 C++17 及更高版本,由于保证省略,因为
LockedSingleton
是不可复制的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.