[英]Thread-safe singleton using atomic
Just want to know whether atomic_flag = 1;
只想知道
atomic_flag = 1;
keeps the myclass_st assignment thread-safe or not.保持 myclass_st 分配线程安全与否。 (I am sorry that my example has so many problems, so I have changed it.)
(对不起,我的例子有这么多问题,所以我改了。)
myClass* myclass_st = nullptr;
std::atomic<int> atomic_flag;
std::mutex mtx; //err
myClass* get_instance() {
//std::unique_lock<std::mutex> lk(mtx);
if (myclass_st == nullptr) {
mtx.lock();
if (myclass_st == nullptr) {
myclass_st = new myClass();
atomic_flag = 1;
mtx.unlock(); //err
}
}
return myclass_st;
}
I know we can use static
after c11.我知道我们可以在 c11 之后使用
static
。
Maybe I should modify the code like this?也许我应该像这样修改代码?
myClass* myclass_st = nullptr;
std::atomic<int> atomic_flag;
myClass* get_instance() {
if (atomic_flag.load() == 0) {
std::unique_guard<std::mutex> lk(mtx);
if (atomic_flag.load() == 0) {
myclass_st = new myClass();
atomic_flag = 1;
}
}
return myclass_st;
}
The shown code is not threaded save, because std::mutex mtx;
显示的代码不是线程保存的,因为
std::mutex mtx;
is a new object each time.每次都是新的 object。 The
std::mutex mtx;
std::mutex mtx;
has to be static so that it is the same mutex for each invocation of
get_instance` but even then the manual locking and unlocking of the mutex would not be valid in the current form.必须是
static so that it is the same mutex for each invocation of
但即便如此,手动锁定和解锁互斥锁在当前形式下也无效。
EDIT after moving the std::mutex mtx;
移动
std::mutex mtx;
后编辑; out of the function the mutex is the same for each invocation of get_instance
.在 function 中,每次调用
get_instance
的互斥锁都是相同的。 But it is still not threaded save.但它仍然不是线程保存。 Multiple threads could pass the first
if (myclass_st == nullptr) {
condition where myclass_st
is nullptr
.多个线程可以通过第一个
if (myclass_st == nullptr) {
myclass_st
为nullptr
的条件。 If there are eg more then three threads that pass the first if
then the thread that first calls lock
will set myclass_st
and release its lock on the mutex.如果有例如超过三个线程通过第一个
if
那么第一个调用lock
的线程将设置myclass_st
并释放它在互斥锁上的锁。 The second thread that called lock
won't release its acquired lock, so all other threads that passed the first if
are blocked.第二个调用
lock
的线程不会释放它获得的锁,因此所有其他通过第一个if
的线程都被阻塞。
It has to be either:它必须是:
myClass* get_instance() {
mtx.lock();
if (myclass_st == nullptr) {
myclass_st = new myClass();
atomic_flag = 1;
}
mtx.unlock();
return myclass_st;
}
Instead of manually locking and unlocking you normally want to do the locking with a lock guard with automatic storage duration (RAII idiom), because that ensures that the lock on the mutex is always released when get_instance
is left.您通常不想手动锁定和解锁,而是使用具有自动存储持续时间(RAII 习惯用法)的锁守卫进行锁定,因为这样可以确保在离开
get_instance
时始终释放互斥锁上的锁。
myClass* get_instance() {
std::lock_guard<std::mutex> lk(mtx);
if (myclass_st == nullptr) {
myclass_st = new myClass();
atomic_flag = 1;
}
return myclass_st;
}
EDIT No neither the first nor the second example is thread save.编辑不,第一个和第二个示例都不是线程保存。 For the second example as you show it the
if (atomic_flag.load() == 0) { /**... **/ atomic_flag = 1;}
could still be entered by two threads.对于您展示的第二个示例,
if (atomic_flag.load() == 0) { /**... **/ atomic_flag = 1;}
仍然可以由两个线程输入。 So new myClass
could still be done multiple times.所以
new myClass
仍然可以多次完成。
Just want to know whether atomic_flag = 1;
只想知道 atomic_flag = 1; keeps the myclass_st assignment thread-safe or not.
保持 myclass_st 分配线程安全与否。
No.不。
Maybe I should modify the code like this?
也许我应该像这样修改代码?
myClass* myclass_st = nullptr; std::atomic<int> atomic_flag; myClass* get_instance() { if (atomic_flag.load() == 0) { myclass_st = new myClass(); atomic_flag = 1; } return myclass_st; }
If you intent get_instance
to be called by multiple threads, then no.如果您打算让多个线程调用
get_instance
,那么不会。
I guess you want:我猜你想要:
myClass* myclass_st = nullptr;
std::atomic<int> atomic_flag{0};
std::mutex mtx;
myClass* get_instance() {
if (atomic_flag == 0) {
std::unique_lock<std::mutex> lk(mtx);
if (myclass_st == nullptr) {
myclass_st = new myClass();
atomic_flag = 1;
}
}
return myclass_st;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.