Volatile and multithreading: is the following thread-safe?

时光毁灭记忆、已成空白 提交于 2019-12-28 16:33:10

问题


Assume there are two threads running Thread1() and Thread2() respectively. The thread 1 just sets a global flag to tell thread 2 to quit and thread 2 periodically checks if it should quit.

volatile bool is_terminate = false;

void Thread1()
{
    is_terminate = true;
}

void Thread2()
{
    while (!is_terminate) {
        // ...
    }
}

I want to ask if the above code is safe assuming that access to is_terminate is atomic. I already know many materials state that volatile can not insure thread-safety generally. But in the situation that only one atomic variable is shared, do we really need to protect the shared variable using a lock?


回答1:


It is probably sort of thread-safe.

Thread safety tends to depend on context. Updating a bool is always thread safe, if you never read from it. And if you do read from it, then the answer depends on when you read from it, and what that read signifies.

On some CPUs, but not all, writes to an object of type bool will be atomic. x86 CPUs will generally make it atomic, but others might not. If the update isn't atomic, then adding volatile won't help you.

But the next problem is reordering. The compiler (and CPU) will carry out reads/writes to volatile variables in the order specified, without any reordering. So that's good.

But it makes no guarantee about reordering one volatile memory access relative to all the non-volatile ones. So a common example is that you define some kind of flag to protect access to a resource, you make the flag volatile, and then the compiler moves the resource access up so it happens before you check the flag. It's allowed to do that, because it's not reordering the internal ordering of two volatile accesses, but merely a volatile and a non-volatile one.

Honestly, the question I'd ask is why not just do it properly? It is possible that volatile will work in this situation, but why not save yourself the trouble, and make it clearer that it's correct? Slap a memory barrier around it instead.




回答2:


It is not thread safe.

If the threads, for example, are run on CPUs with separate caches there are no language rules saying that the caches are to be synchronized when writing a volatile variable. The other thread may not see the change for a very long time, if ever.


To answer in another way:

If volatile is enough to be thread safe, why is C++0x adding an entire chapter with atomic operations?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2047.html




回答3:


First, volatile is used for disabling compile optimization in c/c++. see this for understanding volatile.

The core of atomic is word align and size of is_terminate, if size of is_terminate is less than machine native size and aligned, then R and W of it is atomic.

In your context, with or without volatile, thread2 may read old value after thread1 modified it, but thread2 can read it eventually.

If eventually-read is OK for you, then your codes are thread safety.




回答4:


it's safe because one thread is only reading and one is only writing.

The threads aren't really sharing that flag, one is reading, one is writing. You can't have a race because the other thread will never write a bad result, and the reading thread will never read a bad result. simple.




回答5:


No, it is not. It could be thread safe if the value access was atomic, but in C++ you can't assume that variables access is thread-safe unless you use some compiler-specific constructs or synchronization primitives.




回答6:


It is still not safe. You should use synchronizaton to access is_terminate Access to the bool is not guaranteed to be an atomic operation.




回答7:


I believe that this code is safe, until both the threads are not writing the bool (already you have mentioned that value access is atomic).




回答8:


The big problem with assuming that the volatile keyword imposes any kind of thread safety, is that the C or C++ standards have no concept of threads in the abstract machine they describe.

The guarantees that the standard imposes on the volatile keyword, are only valid within a thread - not between multiple threads.

This leaves implementors with full liberty to do whatever they please when it comes to threads. If they chose to implement the volatile keyword to be safe across threads, then you're lucky. More often than not, that's not the case though.




回答9:


This code isn't seems to be thread safe. Reason can be explained easily.

Problem lies in below code line

"is_terminate = true;"

Even if access to "is_terminate" is atomic, above statement is not atomic. This statement includes more than 1 operations. Like load "is_terminate" and update "is_terminate".

Now gotcha is if is_terminate is loaded and not updated and thread switches to another one. Now thread 2 expected result to be true but it won't get it.

Make sure "is_terminate = true;" is atomic. So lock it.

Hope it helps.



来源:https://stackoverflow.com/questions/6592287/volatile-and-multithreading-is-the-following-thread-safe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!