Windows操作系统中的线程安全和原子读取

ali*_*hoo 2 c++ windows multithreading atomic thread-safety

我在我的应用程序中有这段代码.我怀疑它不是线程安全的,所以决定问问SOers.

int * volatile int_ptr;
int count;
Run Code Online (Sandbox Code Playgroud)

线程1:

void grow(int new_count)
{
    if(new_count <= count) return;
    int * new_ptr = new int[new_count];
    memset(new_ptr, 0 , new_count * sizeof(int));
    memcpy(new_ptr,int_ptr,count);
    int * dum_ptr = (int *)InterlockedExchange((volatile long *)&int_ptr,(long)new_ptr)     
    count = new_count;
    delete [] dum_ptr;
}
Run Code Online (Sandbox Code Playgroud)

线程2:

int get_value(int index)
{
    return int_ptr[index];
}
Run Code Online (Sandbox Code Playgroud)

我知道可以使用CRITICAL_SECTION,但是线程1可以在一周内工作一次,而线程2可以在一天内工作数百万次.在99.99999%的尝试中int_ptr,第二个线程将进入和退出临界区.这对我来说没有意义.该应用程序仅适用于Windows 2000及更高版本,其中英特尔处理器显然具有多核.

这段代码是线程安全的吗?如果没有,我该怎么做才能使它具有线程安全性?我怎么能原子地读取int_ptr?即:

int * dummy_ptr = read_atomic<int *>(int_ptr);
return dummy_ptr[index];
Run Code Online (Sandbox Code Playgroud)

解决方案,包括std::vector,让我更快乐,更舒适.

bdo*_*lan 7

不,这不安全.get_value可以读取值int_ptr,然后计划出来.然后另一个线程可以换出int_ptrdelete旧值.当get_value交换回来时,它会尝试取消引用它读取的值int_ptr- 已经删除了.

一种更好的方法是基于"读取 - 复制 - 更新"(RCU),它已经在Linux中发挥了很大的作用.基本原则是你不要立即删除旧值 - 你等到某个时间点,你可以保守地确定没有任何东西仍然有旧的指针值,然后删除它.

不幸的是,Windows上还没有RCU库实现.我想你可以尝试将urcu移植到Windows.