疑惑,一个方法同步了为什么中间还有yield让步

问题描述

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状态如有线程调用该方法还是会被锁住的,只不过这段代码让其他线程先运行而已
解决方案十:
可能是说让步时间长短随机.

时间: 2024-09-22 07:38:01

疑惑,一个方法同步了为什么中间还有yield让步的相关文章

java 多线程-下面两个方法同步吗,请说明理由,有什么方法可以验证?

问题描述 下面两个方法同步吗,请说明理由,有什么方法可以验证? class Test { synchronized static void say Hello3() { } synchronizedvoid getX() {} } 解决方案 现实应用如下场景: 一个人名叫王X的人 暗地销售火车票,数量为 SUM=1000; 某个时刻 用户甲从他那里购买了2张. 某个时刻 用户乙从他那里购买了4张. 某个时刻 用户丙从他那里购买了7张. ............... 购买者必须轮流购买火车票.

Remote Scripting进阶教程---调用 Remote Scripting 方法同步

调用 Remote Scripting 方法同步在对某个客户页和某个服务器页上的 remote scripting 进行配置后,您就可以从自己的客户脚本调用该服务器页的方法了.缺省的情况是,当用户调用某个服务器方法时,它被同步执行──您的客户脚本直到服务器方法执行完毕并返回结果后才能停止运行.一般说来,当您在自己的客户脚本中需要服务器方法结果时,则需同步调用服务器方法.注意 您也可以异步调用服务器方法.有关详细信息,请参阅异步调用 Remote Scripting 方法.当您调用某个服务器方法时

jquery中一个方法中动态生成的标签可以被其它方法调用吗

问题描述 jquery中一个方法中动态生成的标签可以被其它方法调用吗 解决方案 在控制台中动态引入jquery的方法jquery几个按钮同时调用一个方法 解决方案二: 可以,就根据div的id或者class找到他,$("#xxxx") 解决方案三: 你应该取得添加的那个JS对象 var dd = $('#attr_info').append(......) 然后再$(dd).eq(..).keyup 解决方案四: 看你代码append是动态添加的item吧..这样你的ajax都没添加到

php-PHP一个方法根据传递值怎么执行多次?

问题描述 PHP一个方法根据传递值怎么执行多次? php代码 function one($type='OfferGetAllOfferList',$start,$pagesize=10,$total=100) { $next=$start+1; if($start*$pagesize<=$total) { $this->outData['next'] = $next; $this->outData['pagesize'] = $pagesize; $this->outData['t

谁有多线程代码!!我想实现10个线程同时执行一个方法!

问题描述 我想10个线程同时执行一个方法,但是每个方法传入的参数是不一样的!我在网上找了些代码,但是不行,造成线程混乱,谁能教教我啊!!想要实现的是:10个线程同时去登陆网站,然后采集东西.当然我也有10个用户名.10个线程每个线程对应一个用户. 解决方案 解决方案二:分太少了.不然老夫贴出来解决方案三:ThreadPool.QueueUserWorkItem();解决方案四:给你个多线程的例子privatevoidbtnDataUp_Click(objectsender,RoutedEvent

Java中synchronized关键字修饰方法同步的用法详解_java

Java的最基本的同步方式,即使用synchronized关键字来控制一个方法的并发访问. 每一个用synchronized关键字声明的方法都是临界区.在Java中,同一个对象的临界区,在同一时间只有一个允许被访问. 静态方法则有不同的行为.用synchronized关键字声明的静态方法,同时只能够被一个执行线程访问,但是其他线程可以访问这个对象的非静态的synchronized方法.必须非常谨慎这一点,因为两个线程可以同时访问一个对象的两个不同的synchronized方法,即其中一个是静态s

java-如何在页面调用一个方法获取它的值

问题描述 如何在页面调用一个方法获取它的值 <%String strid = request.getParameter(""id"");String giftid=new String(request.getParameter(""id""));System.out.println(strid);int gid=Integer.parseInt(strid);System.out.println(gid);Gift gt

在adodb.php中有没有一个方法可以返回 update语句,影响的行数

问题描述 在adodb.php中有没有一个方法可以返回 update语句,影响的行数 如题在adodb.php中有没有一个方法可以返回 update语句,影响的行数

不用模板,只用ASP+FSO生成静态HTML页的一个方法

asp+|fso|静态|模板 FSO生成静态HTML文件的时候替换模板标签一直是一个很麻烦的问题,至少我是这么认为的,还要别外做一个模板,麻烦!,我今天看见有一个方法可以解决这个问题 如一个正常的index.asp页面,并且用ASP代码调出数据库中的内容,另建一个makehtml.asp的页面,加入一个textarea域,假设为name="body",将index.asp在textarea里调出来,如:<textarea name="body"><