Multi-Threading on different instances of same object in Java Multi-Threading on different instances of same object in Java multithreading multithreading

Multi-Threading on different instances of same object in Java


I've learned that every class byte code is been loaded to the memory once for each class loader, thus when a thread is executing the byte code of some method, and another thread comes along?

Class loading and byte code is irrelevant here. Byte code is a set of assembly-like instructions which the JVM interprets and compiles into native machine code. More than one thread can safely follow the instruction sets encoded into the byte code.

1 thread -> 1 instance - of class Test, no problem

Mostly correct. If there is only a single Thread, then there is not any immediate need to make anything thread safe. However, ignoring thread safety would limit growth and re-usability.

X threads -> 1 instance - of class Test, need to be handled this is clear.

Well, yes, for thread visibility reasons and to ensure that critical regions are executed atomically, using synchronization or locking techniques is fairly important. Of course, it all depends right?! If your class doesn't have state (instance or class variables), then you don't really need to make it thread-safe (think utility class like Java's Executors, Arrays, Collections classes).

X threads -> X respective instances - of class Test, ????

If each thread has its own instance of class Test, and no single instance is shared amongst more than one thread, then this is the same as your first example. If an instance of Test is referenced by two or more threads, then this is the same as your second example.

if the method uses a class level variables, can I be sure it will use the right ones?

Class variables ARE static variables in Java. There are already two answers posted which emphasize the importance of using synchronized to prevent more than one thread from modifying a class variable at the same time. Not mentioned is the importance of using synchronized or volatile to make sure you don't see a stale version of the class variable.


You need to synchronize on the shared resource. If that resource is a class-level field, you should synchronize on the class itself:

public class Foo {  private static int someNumber = 0;  // not thread safe  public void inc_unsafe()  {     someNumber++;  }  // not thread safe either; we are sync'ing here on an INSTANCE of  // the Foo class  public synchronized void inc_also_unsafe()  {     someNumber++;  }  // here we are safe, because for static methods, synchronized will use the class  // itself  public static synchronized void inc_safe()  {     someNumber++;  }  // also safe, since we use the class itself  public static synchronized void inc_also_safe()  {     synchronized (Foo.class) {      someNumber++;    }  }}

Note that {{java.util.concurrent}} provides many more ways to protected shared data than Java's {{synchronized}} keyword. Look into it, as it might be what you want.

(For anyone that wants to claim that int incrementing is already thread-safe, please note this is just an example and the basic concept can be applied to anything.)


Adding to dave's answer, if you have multiple static methods that work on different static members, it is better to synchronize on separate static objects.

public class Foo {  private static int someNumber = 0;  private static int otherNumber = 0;  private static final Object lock1 = new Object();  private static final Object lock2 = new Object();  public static void incSomeNumber() {    synchronized (lock1) {      someNumber++;    }  }  public static void incOtherNumber() {    synchronized (lock2) {      otherNumber++;    }  }}

In this way, two different threads can call incSomeNumber and incOtherNumber at the same time without getting stuck on synchronization.


EDIT

Here is the same example with AtomicInterger. Note that no explicit locking is required. All operations on AtomicIntergers are atomic and implemented using hardware operations. So they result in better performance.

import java.util.concurrent.atomic.AtomicInteger;public class Foo {  private static AtomicInteger someNumber = new AtomicInteger(0);  private static AtomicInteger otherNumber = new AtomicInteger(0);  public static int incSomeNumber() {    return someNumber.incrementAndGet();  }  public static int incOtherNumber() {    return otherNumber.incrementAndGet();  }}