Search code examples
javamultithreadingconcurrencythread-safetyhappens-before

Java Happens-Before and Thread Safety


Suppose I have a class which wraps a HashMap as follows:

public final class MyClass{

     private final Map<String, String> map;

     //Called by Thread1
     public MyClass( int size ){
         this.map = new HashMap<String, String>( size );
     }

     //Only ever called by Thread2
     public final String put( String key, String val ){
        return map.put( key, value );
     }

     //Only ever called by Thread2
     public final String get( String key ){
        return map.get( key );
     }

     //Only ever called by Thread2
     public final void printMap(  ){
       //Format and print the contents of the map
     }

}

This class is initialized via "Thread1". However, the put, get, printMap and other operations are only ever called by "Thread2".

Am I correct in understanding that this class is thread safe as:

  1. Since the reference to the map is declared final, all other threads would see the initial state of the map (happens-before is established).

  2. Since put/get/printMap/etc are only ever called by Thread2, there is no need for mutual-exclusion.

Thank you


Solution

  • So what you are asking is correct assumption. You do not need to make it thread safe if you can guarantee that it is only used this way. You can't pass a half constructed object around in java, so the "Constructor might not be finished" is not possible.

    So if you do

    new Thread(new Runnable() {
    
        public void run() {
              final MyClass instance = new MyClass(10);
              new Thread(new Runnable() {
                   public void run() {
                        instance.put("one", "one");
                          ....
                   }
    
               }).start();
         }
    
    }).start();
    

    You are fine :) This is what you described, created by Thread1 but only used by Thread2. There is no way for the thread to collide with itself.

    Thread-Safe is a different definition where the composed entity may safely be interacted with by multiple threads. In the case you described, that scenario does not happen, since you essentially have a thread that constructs and another that manipulates.