问题描述
classCount{privateintcount=0;privateRandomrand=newRandom(47);//Removethesynchronizedkeywordtoseecountingfail:publicsynchronizedintincrement(){inttemp=count;if(rand.nextBoolean())//YieldhalfthetimeThread.yield();return(count=++temp);}publicsynchronizedintvalue(){returncount;}}
Java编程思想并发这章的一个例子,许多线程共用这个计数器计数(其他代码省略了),书上说“increment()方法使用了Random对象,目的是在从把count读取到中,到递增temp并将其存储回count这段时间里,有大约一半时间产生让步”。主要迷惑的是:用Random是随机yield让步,但increment()方法是synchronized,increment()没有返回前当前线程是锁住Count对象的,中间yield让步,其他线程也不能访问,这样做有意义吗?
解决方案
解决方案二:
yield是放弃对象锁,使当前线程回到可运行状态,其他线程获得此锁,调用yield就已经放弃当前对象的锁了
解决方案三:
yield方法是让出CPU,不释放锁,让出CPU是啥概念,就是让CPU执行其他线程在LZ的代码里,没有看到main方法,没有看到有几个线程,也不知道各个线程都在做些什么事情,没法说这个操作是否必要另:jvm实现者可以自由实现yield,也就是说它只是一个hint,暗示当前线程让出CPU,至于让不让,就不好说了
解决方案四:
呃~~~,说错了一点,yield不放弃锁,但是使当前运行中线程回到可运行状态,并使具有相同优先级的线程能够具有机会运行。在这里就不要从同步的角度来考虑了,而应该从CPU资源来考虑,当多个线程并发执行的时候,如果当前线程不是很急的话,就让它等一等,让别的线程先执行
解决方案五:
<<Thinkinginjava>>并发那一章的例子,//:concurrency/OrnamentalGarden.java.个人认为是在去掉"synchronized"时用的,在同步的时候,有和没有if(rand.nextBoolean())//YieldhalfthetimeThread.yield();
结果一样。在去掉这个同步的时候,有和没有上面的语句,结果差别较大。
解决方案六:
引用2楼的回复:
yield方法是让出CPU,不释放锁,让出CPU是啥概念,就是让CPU执行其他线程在LZ的代码里,没有看到main方法,没有看到有几个线程,也不知道各个线程都在做些什么事情,没法说这个操作是否必要另:jvm实现者可以自由实现yield,也就是说它只是一个hint,暗示当前线程让出CPU,至于让不让,就不好说了
main方法是产生5个线程,每个线程都有各自的一个计数器,同时5个线程又共用Count这个总计数器.代码如下:importjava.util.concurrent.*;importjava.util.*;//总计数器classCount{privateintcount=0;privateRandomrand=newRandom(47);//Removethesynchronizedkeywordtoseecountingfail:publicsynchronizedintincrement(){inttemp=count;if(rand.nextBoolean()){//YieldhalfthetimeThread.yield();}return(count=++temp);}publicsynchronizedintvalue(){returncount;}}//每个计数器线程classEntranceimplementsRunnable{privatestaticCountcount=newCount();privatestaticList<Entrance>entrances=newArrayList<Entrance>();privateintnumber=0;//Doesn'tneedsynchronizationtoread:privatefinalintid;privatestaticvolatilebooleancanceled=false;//Atomicoperationonavolatilefield:publicstaticvoidcancel(){canceled=true;}publicEntrance(intid){this.id=id;//Keepthistaskinalist.Alsoprevents//garbagecollectionofdeadtasks:entrances.add(this);}publicvoidrun(){while(!canceled){synchronized(this){++number;}System.out.println(this+"Total:"+count.increment());try{TimeUnit.MILLISECONDS.sleep(100);}catch(InterruptedExceptione){System.out.println("sleepinterrupted");}}System.out.println("Stopping"+this);}publicsynchronizedintgetValue(){returnnumber;}publicStringtoString(){return"Entrance"+id+":"+getValue();}publicstaticintgetTotalCount(){returncount.value();}publicstaticintsumEntrances(){intsum=0;for(Entranceentrance:entrances)sum+=entrance.getValue();returnsum;}}publicclassOrnamentalGarden{publicstaticvoidmain(String[]args)throwsException{ExecutorServiceexec=Executors.newCachedThreadPool();for(inti=0;i<5;i++)exec.execute(newEntrance(i));//Runforawhile,thenstopandcollectthedata:TimeUnit.SECONDS.sleep(3);Entrance.cancel();exec.shutdown();if(!exec.awaitTermination(250,TimeUnit.MILLISECONDS))System.out.println("Sometaskswerenotterminated!");System.out.println("Total:"+Entrance.getTotalCount());System.out.println("SumofEntrances:"+Entrance.sumEntrances());}}/*Output:(Sample)Entrance0:1Total:1Entrance2:1Total:3Entrance1:1Total:2Entrance4:1Total:5Entrance3:1Total:4Entrance2:2Total:6Entrance4:2Total:7Entrance0:2Total:8...Entrance3:29Total:143Entrance0:29Total:144Entrance4:29Total:145Entrance2:30Total:147Entrance1:30Total:146Entrance0:30Total:149Entrance3:30Total:148Entrance4:30Total:150StoppingEntrance2:30StoppingEntrance1:30StoppingEntrance0:30StoppingEntrance3:30StoppingEntrance4:30Total:150SumofEntrances:150*///:~
解决方案七:
引用2楼的回复:
yield方法是让出CPU,不释放锁,让出CPU是啥概念,就是让CPU执行其他线程在LZ的代码里,没有看到main方法,没有看到有几个线程,也不知道各个线程都在做些什么事情,没法说这个操作是否必要另:jvm实现者可以自由实现yield,也就是说它只是一个hint,暗示当前线程让出CPU,至于让不让,就不好说了
main方法是产生几个线程,每个线程都有一个自己的计数器,所有线程都共享Count这个计数器,无论哪个线程计数器增加都会改变Count计数器。完整代码如下:importjava.util.concurrent.*;importjava.util.*;//总的计数器classCount{privateintcount=0;privateRandomrand=newRandom(47);//Removethesynchronizedkeywordtoseecountingfail:publicsynchronizedintincrement(){inttemp=count;if(rand.nextBoolean()){//YieldhalfthetimeThread.yield();}return(count=++temp);}publicsynchronizedintvalue(){returncount;}}//每个线程自己的计数器classEntranceimplementsRunnable{privatestaticCountcount=newCount();privatestaticList<Entrance>entrances=newArrayList<Entrance>();privateintnumber=0;//Doesn'tneedsynchronizationtoread:privatefinalintid;privatestaticvolatilebooleancanceled=false;//Atomicoperationonavolatilefield:publicstaticvoidcancel(){canceled=true;}publicEntrance(intid){this.id=id;//Keepthistaskinalist.Alsoprevents//garbagecollectionofdeadtasks:entrances.add(this);}publicvoidrun(){while(!canceled){synchronized(this){++number;}System.out.println(this+"Total:"+count.increment());try{TimeUnit.MILLISECONDS.sleep(100);}catch(InterruptedExceptione){System.out.println("sleepinterrupted");}}System.out.println("Stopping"+this);}publicsynchronizedintgetValue(){returnnumber;}publicStringtoString(){return"Entrance"+id+":"+getValue();}publicstaticintgetTotalCount(){returncount.value();}publicstaticintsumEntrances(){intsum=0;for(Entranceentrance:entrances)sum+=entrance.getValue();returnsum;}}publicclassOrnamentalGarden{publicstaticvoidmain(String[]args)throwsException{ExecutorServiceexec=Executors.newCachedThreadPool();for(inti=0;i<5;i++)exec.execute(newEntrance(i));//Runforawhile,thenstopandcollectthedata:TimeUnit.SECONDS.sleep(3);Entrance.cancel();exec.shutdown();if(!exec.awaitTermination(250,TimeUnit.MILLISECONDS))System.out.println("Sometaskswerenotterminated!");System.out.println("Total:"+Entrance.getTotalCount());System.out.println("SumofEntrances:"+Entrance.sumEntrances());}}/*Output:(Sample)Entrance0:1Total:1Entrance2:1Total:3Entrance1:1Total:2Entrance4:1Total:5Entrance3:1Total:4Entrance2:2Total:6Entrance4:2Total:7Entrance0:2Total:8...Entrance3:29Total:143Entrance0:29Total:144Entrance4:29Total:145Entrance2:30Total:147Entrance1:30Total:146Entrance0:30Total:149Entrance3:30Total:148Entrance4:30Total:150StoppingEntrance2:30StoppingEntrance1:30StoppingEntrance0:30StoppingEntrance3:30StoppingEntrance4:30Total:150SumofEntrances:150*///:~
解决方案八:
引用4楼nmyangym的回复:
<<Thinkinginjava>>并发那一章的例子,//:concurrency/OrnamentalGarden.java.个人认为是在去掉"synchronized"时用的,在同步的时候,有和没有if(rand.nextBoolean())//YieldhalfthetimeThread.yield();结果一样。在去掉这个同步的时候,有和没有上面的语句,结果差别较大。
同意,increment()方法上面有注释:Removethesynchronizedkeywordtoseecountingfail在整个代码的下面也有说明,Count.increment()通过使用temp和yield(),增加了不使用synchronized失败的可能性
解决方案九:
yield()方法使当前线程主动让出CPU片段并回到Runnable状态如有线程调用该方法还是会被锁住的,只不过这段代码让其他线程先运行而已
解决方案十:
可能是说让步时间长短随机.