Java Concurrency in Practice

Author: Brian Goetz, Tim Peierls
4.7
All Stack Overflow 149
This Year Stack Overflow 11
This Month Stack Overflow 1

Comments

by anonymous   2019-01-13

In general, yes, it is possible to see a field in a partially constructed state if the field is not published in a safe manner. In the particular case of your question, the volatile keyword is a satisfactory form of safe publication. According to Java Concurrency in Practice:

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer.
  • Storing a reference to it into a volatile field.
  • Storing a reference to it into a final field.
  • Storing a reference to it into a field that is properly guarded by a (synchronized) lock.

For more information, see the following:

by anonymous   2019-01-13

And then I am using volatile, so it will guarantee the consistent view of the variable across all threads.

Thread-safety is already guaranteed by atomic variables. volatile is redundant if you won't reassign the variable. You can replace volatile with final here:

private final AtomicInteger atomInt = new AtomicInteger(3);

Does it mean that I have got complete thread safety or still there are chances of "memory consistency issues"?

At this moment, it's absolutely thread-safe. No "memory consistency issues" might happen with the variable. But using proper thread-safe components doesn't mean that the whole class/program is thread-safe. Problems might take place if interactions between them are incorrect.

Using volatile variables reduces the risk of memory consistency errors ...

volatile variables can only guarantee visibility. They don't guarantee atomicity.

As Brian Goetz writes (emphasis mine):

volatile variables are convenient, but they have limitations. The most common use for volatile variables is as a completion, interruption, or status flag. Volatile variables can be used for other kinds of state information, but more care is required when attempting this. For example, the semantics of volatile are not strong enough to make the increment operation (count++) atomic, unless you can guarantee that the variable is written only from a single thread.

You can use volatile variables only when all the following criteria are met:

  • Writes to the variable do not depend on its current value, or you can ensure that only a single thread ever updates the value;
  • The variable does not participate in invariants with other state variables;
  • Locking is not required for any other reason while the variable is being accessed.

From the docs of the java.util.concurrent.atomic package:

  • get has the memory effects of reading a volatile variable.
  • set has the memory effects of writing (assigning) a volatile variable.
by anonymous   2019-01-13

There are 2 points when reasoning about thread safety of a particulcar class :

  1. Visibility of shared state between threads.
  2. Safety (preserving class invariants) when class object is used by multiple threads through class methods.

Shared state of Example class consists only from one Thing object.

  1. The class isn't thread safe from visibility perspective. Result of setThing by one thread isn't seen by other threads so they can work with stale data. NPE is also acceptable cause initial value of thing during class initialization is null.
  2. It's not possible to say whether it's safe to access Thing class through use method without its source code. However Example invokes use method without any synchronization so it should be, otherwise Example isn't thread safe.

As a result Example isn't thread safe. To fix point 1 you can either add volatile to thing field if you really need setter or mark it as final and initialize in constructor. The easiest way to ensure that 2 is met is to mark use as synchronized. If you mark setThing with synchronized as well you don't need volatile anymore. However there lots of other sophisticated techniques to meet point 2. This great book describes everything written here in more detail.

by anonymous   2019-01-13

From Java Concurrency in Practice 15.2.3 CAS support in the JVM :

On platforms supporting CAS, the runtime inlines them into the appropriate machine instruction(s); in the worst case, if a CAS-like instruction is not available the JVM uses a spin lock.

by anonymous   2019-01-13

It's well described in Java Concurrency in Practice:

The lazy initialization holder class idiom uses a class whose only purpose is to initialize the Resource. The JVM defers initializing the ResourceHolder class until it is actually used [JLS 12.4.1], and because the Resource is initialized with a static initializer, no additional synchronization is needed. The first call to getresource by any thread causes ResourceHolder to be loaded and initialized, at which time the initialization of the Resource happens through the static initializer.

Static initialization

Static initializers are run by the JVM at class initialization time, after class loading but before the class is used by any thread. Because the JVM acquires a lock during initialization [JLS 12.4.2] and this lock is acquired by each thread at least once to ensure that the class has been loaded, memory writes made during static initialization are automatically visible to all threads. Thus statically initialized objects require no explicit synchronization either during construction or when being referenced.

by anonymous   2018-03-19

Although there are some good answers already posted, but here is what I found while reading Java Concurrency in Practice Chapter 3 - Sharing Objects.

Quote from the book.

The publication requirements for an object depend on its mutability:

  • Mutable objects can be published through any mechanism;
  • Effectively immutable objects (whose state will not be modified after publication) must be safely published;
  • Mutable objects must be safely published, and must be either threadsafe or guarded by a lock.

Book states ways to safely publish mutable objects:

To publish an object safely, both the reference to the object and the object's state must be made visible to other threads at the same time. A properly constructed object can be safely published by:

  • Initializing an object reference from a static initializer;
  • Storing a reference to it into a volatile field or AtomicReference;
  • Storing a reference to it into a final field of a properly constructed object; or
  • Storing a reference to it into a field that is properly guarded by a lock.

The last point refers to using various mechanisms like using concurrent data structures and/or using synchronize keyword.

by anonymous   2018-03-19

An explanation is given with an example in Java Concurrency In Practice chapter 4 section 4.3.5.

public class SafePoint {
    private int x, y;

    private SafePoint(int[] a) {
        this(a[0], a[1]);
    }

    public SafePoint(SafePoint p) {
        this(p.get());
    }

    public SafePoint(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public synchronized int[] get() {
        return new int[] { x, y };
    }

    public synchronized void set(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

The private constructor exists to avoid the race condition that would occur if the copy constructor were implemented as this(p.x, p.y).

What does it mean is, if you did not have a private constructor and you implement copy constructor in following way:

public SafePoint(SafePoint p) {
    this(p.x, p.y);
}

Now assume that thread A is having the access to SafePoint p is executing above copy constructor's this(p.x, p.y) instruction and at the unlucky timing another thread B also having access to SafePoint p executes setter set(int x, int y) on object p. Since your copy constructor is accessing p's x and y instance variable directly without proper locking it could see inconsistent state of object p.

Where as the private constructor is accessing p's variables x and y through getter which is synchronized so you are guaranteed to see consistent state of object p.

by nmg   2017-12-01
In the talk "Clojure Concurrency" [1], Rich Hickey demands that everyone in the room read "Java Concurrency in Practice" [2]. "It will scare the crap out of you."

[1] https://youtu.be/dGVqrGmwOAw?t=23m57s [2] https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz...

by mindcrime   2017-10-02
Wow, that's actually kinda tough to answer. There's been a LOT of changes in the Java world in the last 10 years - as you might guess. And I mean both in terms of the language itself, and the tooling and ecosystem as far as libraries and frameworks, etc.

The answer also depends a bit on what exactly you want to do. If you're mainly interested in web apps, it's one thing, "big data" is another world altogether, mobile (Android) has its own ecosystem, etc.

All of that said, here are some thoughts:

Generics and the newer Collections related stuff is one area that changed a lot. There's online documentation at:

https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz...

To get started with the Java 8 stuff, a book like "Java 8 in Action" would be good.

https://www.amazon.com/Java-Action-Lambdas-functional-style-...

Another good intro the Java 8 era stuff is

https://www.amazon.com/Beginning-Java-Language-Features-Expr...

And to make it even harder, Java 9 just dropped, so there's even more new stuff. I just picked up this book myself, but haven't had a lot of time to dig into it yet.

https://www.amazon.com/Java-Programmers-4th-Deitel-Developer...

For frameworks, Spring and Hibernate are both still popular and it wouldn't hurt to brush up on both of those. Spring Boot in particular has caught on for a lot of Java developers.

https://www.amazon.com/Spring-Boot-Action-Craig-Walls/dp/161...

Also, Tomcat is still very popular for hosting java Web applications and services of various sorts. JBoss / Wildfly is still around, but JEE (as J2EE is now known) is not as popular as in the past (even though it has actually improved a LOT).

Play and Dropwizard are two more frameworks you might want to familiarize yourself with

https://www.playframework.com/

http://www.dropwizard.io/1.1.4/docs/

In terms of tools, Eclipse is still popular, IntelliJ is probably the most popular Java IDE these days, and Netbeans seems to have faded from view a bit. Ant has fallen out of favour for builds, with most devs now using either Maven or Gradle. Read up on / play around with both of those and you'll be in good shape there.

Also, Java shops have also been affected by the overall move to "The Cloud" and you can't really ignore that either. If you haven't already, you'll probably want to familiarize yourself with AWS and the AWS SDK.

If you want to work/play in the "big data" space, you'll need some combination of Hadoop, Kafka, Spark, Hive, Storm, Flume, HBase, Impala, etc., etc., etc.

by MDC   2017-08-20

I know this is a cross post from here... but, I think one of the best Java books is Java Concurrency in Practice by Brian Goetz. A rather advanced book - but, it will wear well on your concurrent code and Java development in general.