Does Java thread-safety apply to all instances of a class or just shared instances? Does Java thread-safety apply to all instances of a class or just shared instances? multithreading multithreading

Does Java thread-safety apply to all instances of a class or just shared instances?


Your assumptions about thread safety are correct. It boils down to fields/state on the same instance being modified by multiple threads.

In your first question the threads all manipulate their own instance of Dog so the approach is thread safe.

In the second question the instance is passed into the static method so once again your working with different instances of the class. If the Dog class contained static fields and the static method manipulated those fields that would not be thread safe, but non final static fields are really never thread safe.


It's not really about shared instances. It's about shared state

With that in mind:

1: correct - if your threads do not operate on shared state, they are inherently thread safe.

2: Incorrect (sorta): - In the specific example of this specific static method, no shared state is touched, but static methods can create/maninpulate shared state.

3: See 1 and 2

As an example, let's introduce a small bit of shared state into the OP's Dog class:

    static Integer numberOfBarksToday=0; 

Because it's static, it's shared. So now, a static method (a modified version of the OP's makeWoof method) can manipulate that:

    public static void makeWoof(Dog dog) {        dog.woof();        synchronized(Dog.numberOfBarksToday) {            Dog.numberOfBarksToday++;        }    }       

I just realized that when I created the example above, I synchronized the access out of habit. With that synchronization, this particular access is thread-safe (though of course all other accesses to numberOfBarksToday have to be synchronized as well).

Without the synchronization, with multiple threads calling this method, you will tend to undercount the number of barks today:T0) numberOfBarksToday=0;T1) thread A checks number of barks (first part of ++), gets 0.T2) thread B checks number of barks, gets 0.T3) thread A sets number of barks to 1T4) thread B sets number of barks to 1

And that's without considering whether in the shared object, the assignment method is atomic.

The synchronization prevents all of the above, plus introduces a memory barrier so that all threads see the same value for numberOfBarksToday.


You asked about how a static method might potentially introduce threading concerns. Below I provided a code example with comments. Note that nothing stops non-static methods from modifying static variables, so the static method is not necessarily more "dangerous" than the instance method.

As CPerkins pointed out, it's most pragmatic to think of threading concerns in terms of "shared state" vs. "unshared state" instead of in terms of classical programming scopes like "class-level (static) variable" "instance-level (member) variable", "private variable", "public variable", "class-level method", "instance-level method". Following some best-practices with regards to classic OO scoping can help guide you towards writing thread-safe code, but ultimately it is the programmer's responsibility to track down what is and isn't shared between threads, and coordinate access (read/write) to shared resources appropriately.

public class Dog{    private static boolean isWagging;    private boolean isWoofing;    public void woof()    {        this.isWoofing = true;    }    public static void wag()    {        isWagging = true;    }    public static void makeWoof(Dog dog)    {        /**         * Thread safety: woof() only modifies instance variables of 'Dog'.         * So if no dog instances are shared between threads, then no         * instance variables of any Dog are shared between threads, and so         * (as long as we do not share any Dog across threads) then there is         * no concern about needing to control access to shared state. Note         * that woof() *could* be changed to also modify 'isWagging' which         * is a static variable, and thus not protected by the "Dog         * instances are not shared between threads" contract. There is no         * guarantee that just because a method is an "instance" method, it         * will not modify shared state. It is a good general practice for         * member methods to only modify member variables, but sometimes         * modifying shared state (e.g. a database) in a member method is         * somewhat unavoidable.         */        dog.woof();        /**         * Thread safety: wag() is a static method that operates on a static         * variable. Instances of Dog do not get separate copies of static         * variables, as the nature of 'static' means that the variable is         * attached to the Dog _class_ itself, not to _instances_ of the Dog         * class. You could say that, in the current implementation, if         * *any* dog wags, then all dogs will be marked as wagging, which is         * probably not what we want. Additionally, since there is no         * synchronization mechanism being used, there is no guarantee that         * other threads will see that that the value of 'isWagging' has         * been updated.         */        wag();        /**         * Additional note: Java makes the static/non-static issue confusing         * by allowing the following syntax to compile. The following syntax         * *might* lead some programmers to believe that some dogs can be         * wagging while others are not. Most compilers will warn you about         * this syntax because it misleadingly makes it appear as if         * isWagging is an instance variable, and wag is an instance method         * (which is not the case.)         */        if (!dog.isWagging)        {            dog.wag();        }        /**         * To be less ambiguous, you should really write the above code as:         */        if (!isWagging)        {            wag();        }        /**         * Or even better: do not use any non-final static variables in your         * program at all.         */    }}