importjava.util.ArrayList;importjava.util.concurrent.Callable;importjava.util.concurrent.ExecutionException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.Future;publicclassCachedThreadPool{privatestaticintid=0;publicstaticvoidmain(String[]args){newCachedThreadPool().fun();}privatevoidfun(){ExecutorServiceexe=Executors.newCachedThreadPool();ArrayListlist=newArrayList();for(inti=0;i
2 回答
白板的微信
TA贡献1883条经验 获得超3个赞
因为放到TaskCall里之后,synchronized表示在一个TaskCall实例上同步执行。有3个实例,它们之间是不同步的。而放在外面是在一个CachedThreadPool中同步。
一只斗牛犬
TA贡献1784条经验 获得超2个赞
按你的测试代码,楼上回答能解释。然而:测试代码有错误,以下是正确的测试代码:importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importjava.util.concurrent.*;publicclassCachedThreadPool{privatestaticintid=0;privatestaticListresults=Collections.synchronizedList(newArrayList<>()); publicstaticvoidmain(String[]args)throwsException{newCachedThreadPool().fun();}privatevoidfun()throwsException{ExecutorServiceexe=Executors.newCachedThreadPool();List>list=newArrayList<>(); for(inti=0;i<100;i++){list.add(exe.submit(newTaskCall()));}exe.shutdown();for(Futurefs:list){ fs.get();}//断言for(inti=1;iif(results.get(i)!=results.get(i-1)+1){ thrownewIllegalStateException();}}System.out.println("\n"+results);}privatesynchronizedStringgetId(){++id;System.out.print(id+",");results.add(id);returnid+"";}classTaskCallimplementsCallable{ @OverridepublicStringcall()throwsException{returngetId();}}}然后是分析:先翻译几处代码,以便理解:1.privatesynchronizedStringgetId(){return++id+"";}等价于privateStringgetId(){synchronized(this){return++id+"";}}2.//TaskCallreturngetId();等价于//TaskCallreturnCachedThreadPool.this.getId();可以看到同步范围仅限于this,也就是CachedThreadPool的实例,只有一个。但是static字段是类的字段,不是实例的字段,因此不在加锁范围!然而,同步会刷新代码块内所有用到的变量,不论static与否。而唯一实例使++代码块被单线程独占。两者结合,意外地做到了并发安全。还可以试验一下,synchronized改成synchronized(CachedThreadPool.class){...},并把main标为synchronized,会导致死锁。synchronized的知识:指定了一个同步范围,进出范围时会刷新相关变量,阻止其他线程进入该范围。synchronizedmethod的范围是this,synchronizedstaticmethod的范围是class。补充:如果同一个类有的方法写了synchronized,有的方法没写,也达不到同步。
添加回答
举报
0/150
提交
取消