首先,看如下代码,是一个同步方法锁的例子: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作用
呼啦一阵风
TA贡献1802条经验 获得超6个赞
你的synchronized加在线程的代码里,你要锁应该要把代码放到主线程中
这样,你每new一个Thread,它都持有这个synchronized 的m1方法,并没有其它线程去调用
线程都是调用自己的synchronized 方法,不知道你明白了没有
如果你想加锁,应该把synchronized 写到外部去,或者加上static
添加回答
举报
0/150
提交
取消