How to write a simple thread-safe class using a volatile variable?
The question was not easy for me, because I thought (incorrectly) that knowing everything about the happens-before relation gives one a complete understanding of the Java Memory Model - and the semantics of volatile.
I found the best explanation in this document:
"JSR-133: JavaTM Memory Model and Thread Specification"
The most relevant fragment of the above document is the section "7.3 Well-Formed Executions".
The Java Memory Model guarantees that all executions of a program are well-formed. An execution is well-formed only if it
- Obeys happens-before consistency
- Obeys synchronization-order consistency
- ... (some other conditions must also be true)
Happens-before consistency is usually enough to come to a conclusion about the program behavior - but not in this case, because a volatile write doesn't happen-before another volatile write.
The MyIntegerHolder with volatile is thread-safe, but it's safety comes from the synchronization-order consistency.
In my opinion when Thread B is about to set the value to 7, A doesn't inform B of everything it has done until that moment (as one of the other answers suggested) - it only informs B about the value of the volatile variable. Thread A would inform B about everything (assigning values to other variables) if the action taken by Thread B was read and not write (in that case, there would exist the happens-before relationship between the actions taken by these two threads).
Volatile and multithreading: is the following thread-safe?
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.
What happens if a volatile variable is written from 2 threads?
The keyword volatile
is used to ensure that changes to your Object
will be seen by other Thread
s.
This does not enforce, that non-atomic operations on the Object
will be performed without an other Thread
interfering before the operation is finished.
For enforcing this you will need the keyword synchronized
.
Java: volatile enough to make classes threadsafe?
Reads and writes of references are always atomic in Java, so there is no danger of, for example, seeing the reference in some half-updated state. If this is what you mean by "thread safe" then the operation is thread safe with or without the keyword.
But volatile
is not about atomicity, it affects whether threads can cache writes locally. volatile
would force writes to be written back to main memory and be visible to other threads. If that is what you mean by thread-safe, then yes you need this keyword.
volatile
itself does not affect whether method calls on foo
exclude other threads or not. If that's what you mean you want to use synchronized
, and in a different place.
Does volatile mean it is thread safe
volatile
means that the value will always be fresh; if another thread put a new object into the variable before you, you will see that object.
It does not change the behavior of the value; you cannot magically make an object thread-safe.
When should the volatile keyword be used in C#?
I don't think there's a better person to answer this than Eric Lippert (emphasis in the original):
In C#, "volatile" means not only "make sure that the compiler and the
jitter do not perform any code reordering or register caching
optimizations on this variable". It also means "tell the processors to
do whatever it is they need to do to ensure that I am reading the
latest value, even if that means halting other processors and making
them synchronize main memory with their caches".Actually, that last bit is a lie. The true semantics of volatile reads
and writes are considerably more complex than I've outlined here; in
fact they do not actually guarantee that every processor stops what it
is doing and updates caches to/from main memory. Rather, they provide
weaker guarantees about how memory accesses before and after reads and
writes may be observed to be ordered with respect to each other.
Certain operations such as creating a new thread, entering a lock, or
using one of the Interlocked family of methods introduce stronger
guarantees about observation of ordering. If you want more details,
read sections 3.10 and 10.5.3 of the C# 4.0 specification.Frankly, I discourage you from ever making a volatile field. Volatile
fields are a sign that you are doing something downright crazy: you're
attempting to read and write the same value on two different threads
without putting a lock in place. Locks guarantee that memory read or
modified inside the lock is observed to be consistent, locks guarantee
that only one thread accesses a given chunk of memory at a time, and so
on. The number of situations in which a lock is too slow is very
small, and the probability that you are going to get the code wrong
because you don't understand the exact memory model is very large. I
don't attempt to write any low-lock code except for the most trivial
usages of Interlocked operations. I leave the usage of "volatile" to
real experts.
For further reading see:
- Understand the Impact of Low-Lock Techniques in Multithreaded Apps
- Sayonara volatile
Is a volatile int in Java thread-safe?
Yes, you can read from it and write to it safely - but you can't do anything compound such as incrementing it safely, as that's a read/modify/write cycle. There's also the matter of how it interacts with access to other variables.
The precise nature of volatile is frankly confusing (see the memory model section of the JLS for more details) - I would personally generally use AtomicInteger
instead, as a simpler way of making sure I get it right.
Related Topics
Convert First Letter in String to Uppercase
How to Generate a Random Number Using the C++11 Standard Library
Ensuring C++ Doubles Are 64 Bits
This Declaration Has No Storage Class or Type Specifier in C++
What Is the Use of "Delete This"
Clear Data Inside Text File in C++
C++ Nested Classes Accessibility
Which Sorting Algorithm Is Used by Stl's List::Sort()
Is Extern "C" Only Required on the Function Declaration
In C/C++ Why Does the Do While(Expression); Need a Semi Colon
Generate Random Numbers in C++ at Compile Time
Switch-Case Statement Without Break
Amortized Analysis of Std::Vector Insertion
Is Rebasing Dlls (Or Providing an Appropriate Default Load Address) Worth the Trouble