假设我有一个原子指针:
std::atomic<void*> mItems;
并且在一个函数中,当一个线程需要访问它时,它首先检查它,如果它是null,则线程将为它分配内存:
void* lItems = std::atomic_load_explicit(&mItems, memory_order_relaxed);
if(lItems == nullptr)
{
void* lAllocation = malloc(...);
if(!std::atomic_compare_exchange_strong_explicit(
&mItems,
&lItems,
lAllocation,
memory_order_relaxed,
memory_order_relaxed))
{
free(lAllocation);
}
}
...
但是如果N线程运行此方法并发并看到mItems
等于null,则所有这些都将分配内存,其中N-1将释放agian。
如何用更好的方法编写类似的方法。
答案 0 :(得分:1)
我猜你可以使用一些众所周知的值(比如全局的地址)作为一个其他线程已在进行分配的标志,将指针作为你的互斥锁。
所以,你的值是:NULL - &gt;魔术“正在进行分配”指针 - &gt;实际分配。
代码会执行以下操作:
这种方式只有一个线程进行分配,但是你的其他N-1线程可能正忙着等待。这是否真的更好会有所不同......
答案 1 :(得分:0)
当我得到它时,只要第一个线程执行你的函数就需要那个结构,那么在启动任何线程之前如何移动分配呢?我的意思是,重新排列代码,以便使用原子指针作为参数调用函数,并在生成调用函数的任何线程之前分配结构(如果分配失败,您还可以避免创建任何线程)
类似的东西:
std::atomic<void*> mItems;
void func_that_uses_mItems();
int main()
{
mItems = init_struct();
std::thread t1 { &func_that_uses_mItems };
std::thread t2 { &func_that_uses_mItems };
// ... join with or detach threads ...
return( 0 );
}
如果分配失败,则抛出异常并且不启动任何线程。