繁体   English   中英

访问unsigned char线程安全(原子)

[英]Make access to unsigned char thread-safe (atomic)

我很清楚之前已经提出了类似的问题,而且我也知道,这个操作很可能根本就不是原子的,但是我仍然要求空闲的好奇心,并希望有一些方法可以让它成为原子。

情况:在struct内部,有一个名为Busy的unsigned char变量。 (虽然它可以移出那里并独立站立)。

此变量Busy由两个并发线程修改,一个在调度时设置位,另一个在完成调度操作后清除它们。

现在,调度看起来像这样:

while(SEC.Busy&(1 << SEC.ReqID))
    if(++SEC.ReqID == 5) SEC.ReqID = 0;
sQuery.cData[2] = SEC.ReqID;

而清理bitmaks看起来像这样:

SEC.Busy &= ~(1 << sQuery->cData[2]);

cData [2]基本上携带有关通过网络使用哪个插槽的信息,并通过另一个线程中的回调返回。

现在的问题是:我怎样才能确保SEC.Busy(在这种困境中唯一的变量)不会被两个线程同时试图改变它而不使用互斥锁,关键部分或任何东西而撕裂如果可能的话?

我也尝试将SEC.Busy的内容分配给一个局部变量,改变它然后再写回变量,但不幸的是这个操作似乎也不是原子的。

我目前正在使用Borland C ++ Builder 6,尽管GCC解决方案也可以。

非常感谢你。

C ++ 03(也不是C99)根本没有说明原子性。 在大多数平台上, 赋值是原子的(=每个人都看到旧值或新值),但由于它没有同步(=任何人在看到其他更新的新值之后可能看到旧值),无论如何它都是无用的。 任何其他操作,如增量,设置位等都可能不是原子的。

C ++ 11定义了std::atomic模板 ,它确保原子性和同步,因此您需要使用它。 Boost为大多数C ++ 03编译器提供了兼容的实现,gcc 从4.2开始就内置了支持 ,它被gcc 4.7中C ++ 11所需的更高级支持所取代

Windows API早就有了“互锁操作” 在引入gcc __sync函数之前,Unix替代需要汇编(几个库提供)。

从多个线程访问共享数据时有三个潜在的问题。 首先,您可能会在内存访问过程中获得一个需要多个总线周期的线程切换; 这被称为“撕裂”。 其次,每个处理器都有自己的内存缓存,将数据写入一个缓存不会自动写入其他缓存,因此不同的线程可以看到过时的数据。 第三,编译器可以移动指令,以便另一个处理器可以看到稍后存储到一个变量而不会看到前一个存储到另一个存储。

使用unsigned char类型的变量几乎肯定会删除第一个,但它对其他两个没有任何影响。

要避免所有这三个问题,请使用C ++ 11中的atomic<unsigned char>或编译器和操作系统提供的任何同步技术。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM