關於java對資源加鎖無效的問題
阿新 • • 發佈:2019-01-10
看程式設計思想一書,也寫了段程式碼,發現對static的資源加鎖無效,左思右想終於找出了原因,現貼出與大家分享。
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; class Source { int i=0; } class Generator { public static Integer i=0; public static Source source=new Source(); public static Boolean isCancelled=false; public int next() { /** * 無效的資源加鎖 */ synchronized(i) { i++; Thread.yield(); i++; return i; } /** * 有效的資源加鎖 */ // synchronized(source) // { // source.i++; // Thread.yield(); // source.i++; // return source.i; // } } } class Increase implements Runnable { int id; Generator gen; public Increase(Generator gen,int id) { this.gen=gen; this.id=id; } @Override public void run() { while(gen.isCancelled==false) { int val=gen.next(); if(val%2!=0) { gen.isCancelled=true; print("#"+id+" error. val="+val); } } print("#"+id+" complete. gen:"+gen.next()); // print("#"+id+" complete. gen.i:"+gen.i.); } public static void print(Object obj) { System.out.println(obj); } } public class TestLock { static ExecutorService exec = Executors.newCachedThreadPool(); public static void main(String[] args){ ExecutorService exec = Executors.newCachedThreadPool(); Generator gen=new Generator(); for(int i = 0; i < 10; i++) exec.execute(new Increase(new Generator(), i)); exec.shutdown(); } }
資源加鎖的關鍵是確定所加鎖的資源是否是唯一的,是否的分配的唯一記憶體地址的資源;
上面的無效加鎖原因是:static對基本型i 並沒有分配記憶體,而對於封裝了的資源source
則用new關鍵字進行了初始化,並擁有唯一記憶體,因此對source的加鎖才是對單一資源的加鎖;
而對於資源i ,10個執行緒有10個i到底是對誰加鎖呢?等於是沒有加鎖。
(有不恰當處,歡迎吐槽!!!)