程式扎記: [ GroovyGN ] Synchronized Annotation for Synchronizing Methods

標籤

2014年4月29日 星期二

[ GroovyGN ] Synchronized Annotation for Synchronizing Methods

來源自 這裡 
Preface: 
Since Groovy 1.7.3 we have a new AST transformation: @Synchronized. This annotation is based on the Project Lombok Synchronized annotation. We can use the annotation on instance and static methods. The annotation will create a lock variable in our class (or we can use an existing variable) and the code is synchronized on that lock variable. Normally with the synchronized keyword the lock is on this, but that can have side-effects. 

Example: 
接著來看範例代碼, 知道 @Synchronized 使用的差別. 首先參考代碼如下: 
  1. import groovy.transform.Synchronized  
  2.   
  3. class ThdImpt implements Runnable{  
  4.     public static List Output = new ArrayList()  
  5.     public static int NEXT = 0  
  6.     public int runTimes  
  7.       
  8.     public static NEXT()  
  9.     {  
  10.         return NEXT++;  
  11.     }  
  12.       
  13.     public ThdImpt(int rt){runTimes = rt}  
  14.   
  15.     @Override  
  16.     public void run() {  
  17.         runTimes.times {  
  18.             def next = NEXT()             
  19.             synchronized(Output)  
  20.             {  
  21.                 Output.add(next);  
  22.             }  
  23.         }         
  24.     }     
  25. }  
  26.   
  27. int ThreadOpenCount = 10  
  28. ThreadGroup tg = new ThreadGroup()  
  29. ThreadOpenCount.times {  
  30.     new Thread(tg, new ThdImpt(100)).start()  
  31. }  
  32.   
  33. while(tg.activeCount() > 0) sleep(100)  
  34. printf "\t[Info] Done (%d)!\n", ThdImpt.Output.size();  
  35. Set intSet = new TreeSet()  
  36. ThdImpt.Output.each { num->  
  37.     if(num==null)   
  38.     {  
  39.         printf "Contain null data!\n"  
  40.         return  
  41.     }  
  42.     if(!intSet.add(num))  
  43.     {  
  44.         printf "%d is duplicate!\n", num  
  45.     }  
  46. }  
執行結果可能會發現 "??? is duplicate", 這是因為 NEXT() 方法在多線程情況下, 可能發生下面狀況: 
 

此時 ThreadA 與 ThreadB 就會拿到相同的 NEXT=0. 因此我們需要對 NEXT() API 進行 Synchronization. 在 Groovy 可以使用 @Synchronized 在 static 函數, 確保該函數每次只能被一個線程執行以避免 Race condition. 也就是說在 NEXT() API 加上 @Synchronized 便可以解決 "??? is duplicate" 的問題. 

Supplement: 
JavaTutorial - Synchronized Methods 
Java Synchronized Blocks 
Groovy groovy.transform.Synchronized annotation

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!