Sunday 17 April 2016

Effective Java Item 66: Volatile, synchronization, and AtomicLong

volatile

 class SerialNumber{  
   private static volatile long nextSerialNumber = 0;  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  
   
 public class MyConcurrency extends Thread{  
   
   private static List<Long> numbers = new ArrayList<>();  
   
   private static synchronized void add(long number){  
     numbers.add(number);  
   }  
   
   public static void main(String[] args) throws Exception{  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     new MyConcurrency().start();  
     Thread.sleep(10*1000); //Make sure threads all end  
     Set<Long> hashSet = new HashSet<>();  
     for(long i : numbers) {  
       if(!hashSet.add(i)){  
         System.out.println("Has duplicate "+i);  
       }  
     }  
     System.out.println("Finish");  
   }  
   
   @Override  
   public void run() {  
     long nextSerialNumber;  
     do{  
       nextSerialNumber = SerialNumber.nextSerialNumber();  
       add(nextSerialNumber);  
     }while(nextSerialNumber < 10000);  
   }  
 }  

Found duplicates

 Has duplicate 4528  
 Has duplicate 5280  
 Has duplicate 7274  
 Has duplicate 9376  
 Finish  

Correct implementation using synchronized

 class SerialNumber{  
   private static long nextSerialNumber = 0;  
   
   public static synchronized long nextSerialNumber(){  
     return nextSerialNumber++;  
   }  
 }  

Correct implementation using AtomicLong

 class SerialNumber{  
   private static final AtomicLong nextSerialNumber = new AtomicLong();  
   
   public static long nextSerialNumber(){  
     return nextSerialNumber.getAndIncrement();  
   }  
 }