My guess is that it would be similar with volatile keyword, which gives happened-before relation, visibility and atomic value assignment(in case of >32bit types as long) in Java. Is it?
(edit: my guess was that atomic attribute was similar to volatile, not nonatomic but turns out it wasn't anyway)
"Atomic" in Objective C, according to this article, is similar to a synchronized variable in Java, such that it cannot be changed by two threads at the same time. nonatomic is the opposite, meaning a variable that is not synchronized, and therefore could be changed by multiple threads simultaneously.
Regarding volatile, according to wikipedia:
The Java programming language also has the volatile keyword, but it is used for a somewhat different purpose. When applied to a field, the Java volatile guarantees that:
(In all versions of Java) There is a global ordering on the reads and writes to a volatile variable. This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value. (However, there is no guarantee about the relative ordering of volatile reads and writes with regular reads and writes, meaning that it's generally not a useful threading construct.)
(In Java 5 or later) Volatile reads and writes establish a happens-before relationship, much like acquiring and releasing a mutex.
Using volatile may be faster than a lock, but it will not work in some situations. The range of situations in which volatile is effective was expanded in Java 5; in particular, double-checked locking now works correctly.
Related
We're trying to avoid atomics and reads-to-memory whenever possible in our cloud service product. As a result, we're having a lively debate regarding in-practice eventual consistency (also referred to as eventual visibility) of static variables when Java is running on modern processors.
It is accepted that the Java language specification does not guarantee either cross-thread-update-visibility OR eventual-consistency for multithreaded changes to statically-scoped variables UNLESS they are defined as volatile. Basically, not using the volatile keyword means there are no guarantees about consistency. Use of volatile keyword ensures instruction ordering and immediate visibility/consistency of the variable's latest value across threads.
"A write to a volatile variable v (§8.3.1.4) synchronizes-with all subsequent reads of v by any thread (where "subsequent" is defined according to the synchronization order)." Section 14.4.4 of the Java Language Specification (JLS)
"A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4)." Section 8.3.14 of the Java Language Specification (JLS)
https://dzone.com/articles/java-multi-threading-volatile-variables-happens-be-1
https://wiki.sei.cmu.edu/confluence/display/java/Concurrency%2C+Visibility%2C+and+Memory
However, in practice, when modern commercial CPUs write to a static variable, they do queue a memory update hint of some form to the cache controller, which then eventually forces the memory location to update in cache across cores. And, unless the memory location being read is in a tight loop on a specific thread, normal CPU utilization on enterprise workloads does appear to eventually generate the required cache hints to generate consistency across threads for the non-volatile static variables in practice (barring compiler optimization edge cases that cause weird reordering issues).
As an example, if we have multiple Java threads reading a statically-shared variable with no volatile qualifier, with one thread generating very widely spaced writes to the variable (one every few hours), then Java test code consistently shows threads quickly picking up the value change regardless of not having the volatile qualifier. This is likely due to the underlying OS/CPU architectures invalidating the per-core cache.
So our question is this: Compiler reordering issues aside (e.g. termination conditions in loops), can anyone shed some light on when this OS/CPU not-guaranteed-but-there-in-practice eventual-consistency will not occur?
For example, are there actual Intel/AMD/ARM architectures or flavors of Linux that this not-guaranteed-but-there-in-practice eventual consistency will not occur on? Our tests indicate it always eventually generates consistency on MacOS Linux even without the volatile keyword.
Modern CPU have consistent memory model, so if variable is written to memory it will be visible (can be changed at any moment in the future, so don't rely on that).
Thing that will fail you in practice is JIT, it can decide never store variable in memory at all.
I have good knowledge of synchronization internals and basic knowledge of volatile internals.
I have one query, which is follow-up to below SE question:
Why is volatile used in this example of double checked locking
I'm confused about one part. If I strictly follow above example, I have to add volatile to many variables but I am sure that all multi-threaded applications are not using this volatile + synchronized combination.
If synchronization is not guaranteeing memory consistency as per above example, what are the use cases of using combination of volatile variables with synchronization code?
When a variable is defined volatile it is read from the main memory instead of registries.
So each processor will see the same value.
In the double check the variable is defined as volatile to be sure to check outside of synchronized block will intercept most of cases.
If the variable is not volatile the code will work, but if you have more processors you can go inside of the synchronized block more than needed (also when the variable is not null).
If all access to a variable are done in the synchronized block a volatile is not necessary at all.
The combination of volatile and synchronized in that question/answer only applies to double-checked locking.
If you're not doing double-checked locking, and are accessing your shared variables always within the protection of the same synchronized monitor (which is how applications most commonly access shared variables, if they're not using the java.util.concurrent classes), then you don't need volatile.
In any case, this doesn't mean that double-checked locking is a good idea. Although the volatile + synchronized construct will make double-checked locking work, it doesn't offer any significant performance benefit, as you can also read in #alf's answer to the question you refer to.
From documentation page:
Package java.util.concurrent.atomic Description:
A small toolkit of classes that support lock-free thread-safe programming on single variables. In essence, the classes in this package extend the notion of volatile values, fields, and array elements to those that also provide an atomic conditional update operation of the form
boolean compareAndSet(expectedValue, updateValue);
With many options available in atomic package like
AtomicBoolean
AtomicInteger
AtomicLongArray
etc, can I use these AtomicXXX and slowly get rid of volatile variables in my legacy code?
EDIT:
Keep volatile for single write & multiple read operations in different threads (my conclusion after reading many articles), multi-writer, single-reader cases ( as per #erickson comments)
Use AtomicXXX for multiple updates & multiple reads among multiple threads to avoid synchronization. Provide atomicity to volatile variables.
My thought process has been changed with #ericksoncomments.volatile supports multiple write & single read` but can fail with multiple writes and multiple reads. I am confused on this concept.
Yes, an AtomicXXX instance provides the same visibility guarantees that you get from accessing a volatile field.
However, AtomicXXX do more than volatile fields, and accordingly, they are a bit more expensive to use. Specifically, they provide operations that are more like an optimized synchronized block than a volatile read or write. You increment-and-get, or compare-and-swap—multiple actions, atomically. Volatile variables don't provide any atomicity.
So, switching from volatile to AtomicXXX isn't necessarily a good move. Consider if it makes sense given how data are used, and perhaps do some profiling on a prototype to see what performance impact it will have.
In Java Concurrency In Practice, it says that
A write to a volatile field happens-before every subsequent read of
that same field
Does that mean if two threads try to simultaneously read and write to a volatile field, the JVM will ensure that the write operation precedes the read operation or would there be a race condition anyway ?
There would be a race condition. The outcome would depend on who gets there first:
If the write is first, the happens-before guarantees that the read will see the new value.
If the read is first, the happens-before with the most recent earlier write guarantees that the read will see the value of that write.
A happens-before relationship has an extremely specific meaning in the Java specification. Oracle provides an overview of what it means in their concurrency tutorial.
It's important to understand that the relationship is defined over time spent on the CPU. In other words, it has nothing to do with the initial order in which events occur: a write or a read could come first in your application.
It rather says that if the write is executed first, then the effects of that write will be visible to all threads before they execute subsequent read operations. It just provides memory consistency.
If the write to the volatile field happens before the read of that field, then volatile will guarantee that the read will be the latest value.
Note volatile does not guarantee atomicity, it guarantees visibility.
I know using volatile keyword in Java we get some kind of weak synchronization (It allows visibility updates but do not provide actual locking). Is there any situation where volatile should be given preference over actual locking in implementing concurrent programs. A somewhat similar question is there on SO which says volatile as a synchronization mechanism but that was tagged to C#.
If the shared state consists in a single field, and you don't use any get-and-set construct (like i++ for example) to assign it, then volatile is good enough. Most of the volatile usages can be replaced by the use of AtomicXxx types, though (which provide atomic get-and-set operations).
In short, you should prefer to avoid locks wherever they are not necessary since locks expose your program to deadlocks and deter performance by excluding concurrency from critical parts of code. So, whenever the situation permits, by all means rely on volatile; if all you additionally need is atomic two-step operations like compare-and-swap, use AtomicReference. Fall back to synchronized only for the scenarios where this is the only option. For example, if you need to lazily initialize a heavy object, you'll need locks to prevent double initialization—but again, not to fetch the already initialized instance (double-check idiom).
Volatile guarantees that all threads will see the last write of a variable by any other thread, that's it. There's no synchronization involved. If you synchronize both read and write method of an instance variable, then you don't have to make that variable volatile (all threads will see the most recent write).