简体   繁体   English

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

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

I am well aware that similar questions have been asked before and I'm also aware, that the operation is most likely not atomic at all, but I'm still asking out of idle curiosity and in hope that there's some way to MAKE it atomic. 我很清楚之前已经提出了类似的问题,而且我也知道,这个操作很可能根本就不是原子的,但是我仍然要求空闲的好奇心,并希望有一些方法可以让它成为原子。

The situation: Inside a struct , there's an unsigned char variable called Busy . 情况:在struct内部,有一个名为Busy的unsigned char变量。 (It can be moved out of there and stand on its own though). (虽然它可以移出那里并独立站立)。

This variable Busy is modified by two concurrent threads, one who sets bits on scheduling and one who clears them upon completion of the scheduled action. 此变量Busy由两个并发线程修改,一个在调度时设置位,另一个在完成调度操作后清除它们。

Right now, the scheduling looks like this: 现在,调度看起来像这样:

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

while the clearing of the bitmaks looks like this: 而清理bitmaks看起来像这样:

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

cData[2] basically carries the information about which slot is used over the network and comes back via a callback in another thread. cData [2]基本上携带有关通过网络使用哪个插槽的信息,并通过另一个线程中的回调返回。

Now the question: How can I make sure that SEC.Busy (which is the only variable in this troubled situation) doesn't get torn apart by two threads trying to alter it at the same time without using a mutex, critical section or anything of the likes if possible? 现在的问题是:我怎样才能确保SEC.Busy(在这种困境中唯一的变量)不会被两个线程同时试图改变它而不使用互斥锁,关键部分或任何东西而撕裂如果可能的话?

I've also tried assigning the content of SEC.Busy to a local variable, alter that and then write the variable back, but unfortunately this operation also doesn't seem atomic. 我也尝试将SEC.Busy的内容分配给一个局部变量,改变它然后再写回变量,但不幸的是这个操作似乎也不是原子的。

I'm using Borland C++ Builder 6 at the moment, though a GCC solution would also be just fine. 我目前正在使用Borland C ++ Builder 6,尽管GCC解决方案也可以。

Thank you very much. 非常感谢你。

C++03 (nor C99) does not say anything about atomicity at all. C ++ 03(也不是C99)根本没有说明原子性。 Assignment is atomic (= everybody sees either the old or the new value) on most platforms, but because it is not synchronized (= anybody may see the old value after they saw new value for other updates) on any, it is useless anyway. 在大多数平台上, 赋值是原子的(=每个人都看到旧值或新值),但由于它没有同步(=任何人在看到其他更新的新值之后可能看到旧值),无论如何它都是无用的。 Any other operation like increment, set bit and such is likely not even atomic. 任何其他操作,如增量,设置位等都可能不是原子的。

C++11 defines std::atomic template , which ensures both atomicity and synchronization, so you need to use it. C ++ 11定义了std::atomic模板 ,它确保原子性和同步,因此您需要使用它。 Boost provides compatible implementation for most C++03 compilers and gcc has had built-in support since 4.2 , which is being replaced by more advanced support needed by C++11 in gcc 4.7 Boost为大多数C ++ 03编译器提供了兼容的实现,gcc 从4.2开始就内置了支持 ,它被gcc 4.7中C ++ 11所需的更高级支持所取代

Windows API had "Interlocked operations" since long ago. Windows API早就有了“互锁操作” Unix alternative required assembly (which several libraries provided) before introduction of the gcc __sync function. 在引入gcc __sync函数之前,Unix替代需要汇编(几个库提供)。

There are three potential problems when accessing shared data from multiple threads. 从多个线程访问共享数据时有三个潜在的问题。 First, you might get a thread switch in the middle of a memory access that requires more than one bus cycle; 首先,您可能会在内存访问过程中获得一个需要多个总线周期的线程切换; this is called "tearing". 这被称为“撕裂”。 Second, each processor has its own memory cache, and writing data to one cache does not automatically write to other caches, so a different thread can see stale data. 其次,每个处理器都有自己的内存缓存,将数据写入一个缓存不会自动写入其他缓存,因此不同的线程可以看到过时的数据。 Third, the compiler can move instructions around, so that another processor might see a later store to one variable without seeing a preceding store to another one. 第三,编译器可以移动指令,以便另一个处理器可以看到稍后存储到一个变量而不会看到前一个存储到另一个存储。

Using a variable of type unsigned char almost certainly removes the first one, but it doesn't have any effect on the other two. 使用unsigned char类型的变量几乎肯定会删除第一个,但它对其他两个没有任何影响。

To avoid all three problems, use atomic<unsigned char> from C++11 or whatever synchronizing techniques your compiler and OS provide. 要避免所有这三个问题,请使用C ++ 11中的atomic<unsigned char>或编译器和操作系统提供的任何同步技术。

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

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