两个unique_ptr< T>的无锁交换。 [英] Lock-free swap of two unique_ptr<T>
问题描述
不保证交换两个 unique_ptr
是线程安全的。
Swapping two unique_ptr
s is not guaranteed to be threadsafe.
std::unique_ptr<T> a, b;
std::swap(a, b); // not threadsafe
因为我需要原子指针交换,而且因为我喜欢<$ c的所有权处理$ c> unique_ptr ,有没有一种简单的方法将两者组合?
Since I need atomic pointer swaps and since I like the ownership handling of unique_ptr
, is there a simple way to combine them both?
编辑:如果无法做到这一点,我欢迎其他选择。我至少想做这样的事情:
If this is not possible, I am open for alternatives. I at least want to do something like this:
threadshared_unique_ptr<T> global;
void f() {
threadlocal_unique_ptr<T> local(new T(...));
local.swap_content(global); // atomically for global
}
在C +中,这种做法的惯用方式是什么+11?
What is the idiomatic way of doing this in C++11?
推荐答案
两个指针的无锁交换
似乎没有通用的无锁解决方案可以解决此问题。为此,您可能需要以原子方式将新值写入两个不连续的内存位置。这称为 DCAS
,但在Intel处理器中不可用。
Lock-free swapping of two pointers
It seems there is no general lock-free solution for this problem. To do this, you need a possibility to atomically write new values into two non-continous memory locations. This is called DCAS
, but it is not available in Intel processors.
这是可能的,因为只需要将新值自动保存到 global
并接收其旧值即可。我的第一个想法是使用 CAS
操作。看看下面的代码来了解一下:
This one is possible, as it is only needed to atomically save new value into global
and receive its old value. My first idea was to use CAS
operation. Take a look at the following code to get an idea:
std::atomic<T*> global;
void f() {
T* local = new T;
T* temp = nullptr;
do {
temp = global; // 1
} while(!std::atomic_compare_exchange_weak(&global, &temp, local)); // 2
delete temp;
}
步骤
- 在
temp
中记住当前的 - 如果
全局
仍等于<,则将本地
保存到全局
code> temp (其他线程未更改)。如果不是这样,请再试一次。
global
指针- Remember current
global
pointer intemp
- Save
local
toglobal
ifglobal
is still equal totemp
(it wasn't changed by other thread). Try again if this is not true.
实际上, CAS
在那里过大,因为在更改之前,我们不会对旧的 global
值进行任何特殊处理。因此,我们只可以使用原子交换操作:
Actually, CAS
is overkill there, as we do not do anything special with old global
value before it is changed. So, we just can use atomic exchange operation:
std::atomic<T*> global;
void f() {
T* local = new T;
T* temp = std::atomic_exchange(&global, local);
delete temp;
}
请参见乔纳森(Jonathan)的答案,以获得更简短,更优雅的解决方案。
See Jonathan's answer for even more short and elegant solution.
无论如何,您都必须编写自己的智能指针。您不能在标准 unique_ptr
中使用此技巧。
Anyway, you will have to write your own smart pointer. You can't use this trick with standard unique_ptr
.
这篇关于两个unique_ptr< T>的无锁交换。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!