为了账号安全,请及时绑定邮箱和手机立即绑定

疑惑System.out.println对输出结果的影响,请问该怎么解决?

疑惑System.out.println对输出结果的影响,请问该怎么解决?

胡说叔叔 2022-05-19 12:15:25
首先,看如下代码,是一个同步方法锁的例子:package sync;public class TT implements Runnable{int b=100;//第三处 int c=100;public synchronized void m1(){//(第一处)System.out.println(Thread.currentThread().getName());b=1000;System.out.println(Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("b="+b);}public synchronized void m2(){//(第二处)System.out.println(Thread.currentThread().getName());try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}b=2000;}public void run(){m1();}public static void main(String[] args) {TT tt=new TT();Thread t=new Thread(tt);t.start();tt.m2();//第四处:System.out.println(tt.c);System.out.println(tt.b);//第五处:System.out.println(tt.c);}m1和m2 方法都用了synchronized同步。我是这样理解的,但不知道是否正确:当主线程main调用tt.m2()方法,获得了方法锁,并且锁住了变量b。线程t无法继续执行m1()方法,因为m1()要对变量b进行操作,只有等m2方法执行完毕后,才能执行。System.out.println(tt.b);带来的结果是b=1000;以上程序执行后的结果如下:1000Thread-0b=1000那么问题来了!情况1:当在程序第一处或者程序第二处位置添加语句:System.out.println(Thread.currentThread().getName());都会造成输出结果的改变,System.out.println(tt.b);带来的结果是b=2000;情况2:在源程序基础上,在第二处添加语句:System.out.println(Thread.currentThread().getName());原本最后System.out.println(tt.b);带来的结果是b=2000。但是,如果继续在//第三处添加int c=100;并且在//第四处添加System.out.println(tt.c);那么运行后,System.out.println(tt.b);带来的结果又变为b=1000;如果,把//第四处System.out.println(tt.c);放在//第五处的位置上System.out.println(tt.b);带来的结果又变为b=2000;m1和m2方法中的sleep方法中的值,也对组后的输出结果有影响。在测试时,偶然发生过,但并不规律。求指点。
查看完整描述

2 回答

?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

java虚拟机对于线程的调度是无法直接操控的,只要有线程,具体执行那个线程也是无法预知的,你的这个情况很大一部分是巧合与运气
唯一的解释是System.out.println(Thread.currentThread().getName());是一个耗时操作与sleep方法拖延的时间不相上下,你的sync关键字甚至没起到作用
你把b=2000改成b+=2000;
然后试试加sync与不加,如果不加,执行t.start();tt.m2();后b有可能等于1100 2100 或者3100虽然可能性不大,因为这个小程序线程切换的几率不大
加了sync就能保证100加1000再加2000后是3100,而不是其他的过期数据,这才是sync作用

查看完整回答
反对 回复 2022-05-23
?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

你的synchronized加在线程的代码里,你要锁应该要把代码放到主线程中
这样,你每new一个Thread,它都持有这个synchronized 的m1方法,并没有其它线程去调用
线程都是调用自己的synchronized 方法,不知道你明白了没有
如果你想加锁,应该把synchronized 写到外部去,或者加上static

查看完整回答
反对 回复 2022-05-23
  • 2 回答
  • 0 关注
  • 212 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信