synchronized锁定变量吗

烟草味淡淡 2011-10-07 10:35:08

public class TT implements Runnable {
private int b = 100;

public void m1() {
synchronized (this) {
try {
Thread.sleep(3000);
b = 1000;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b1 = " + b);
}
}

public void m2() {
System.out.println("b2 = " + b);
}

public void run() {
this.m1();
}

public static void main (String[] args) throws Exception {
TT t = new TT();
Thread t1 = new Thread(t);
t1.start();
Thread.sleep(500);
t.m2();
}
}


输出
b2 = 100
b1 = 1000

如果把最后那个Thread.sleep(500)改成5000
那输出
b2 = 1000
b1 = 1000

请问下为什么输出不同。m1方法执行过程中
为什么m2方法可以调用b变量啊。
我自己理解。 synchronized锁定后。其中的代码都锁定了。
谢谢
...全文
753 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
烟草味淡淡 2011-10-08
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 qizaodian 的回复:]

引用 3 楼 sammiriche 的回复:
引用 2 楼 qizaodian 的回复:

1, m1()中有 sleep(3000) 3000>500, 所以先是执行t.m2(),再执行t.m1()
2, 而把sleep(500)改为sleep(5000)后,执行的顺序就要反过来了,m1()中的变量b被修改了,所以两个输入都是1000
3, m2()是TT类中的成员方法,当然可以调用……
[/Quote]
起码我认为你说的 而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程
这句话不对,对象锁定状态。sleep是不会跳出对象锁的。

我比较认可 synchronized锁定的变量其他的非同步方法依然可以访问 这种说法
shupo 2011-10-08
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 itbasketplayer 的回复:]
锁定一个对象,那里面不同步的方法是可以被访问的,只是同步方法里面的不能访问
[/Quote]
学习一下子
  • 打赏
  • 举报
回复
锁定一个对象,那里面不同步的方法是可以被访问的,只是同步方法里面的不能访问
lliiqiang 2011-10-08
  • 打赏
  • 举报
回复
因为m2()方法没有同步,只有同步代码块之间存在互斥,同步的和非同步的之间不互斥
public synchronized void m2() {//把m2也同步了
System.out.println("b2 = " + b);
}
杀猪剑客 2011-10-08
  • 打赏
  • 举报
回复
建议看下 马士兵的多线程视频。这个视频讲的很详细。 如果你在m2方法上也加锁,那么就会在整个对象上同步。
zhengming_snsoft 2011-10-08
  • 打赏
  • 举报
回复
个人觉得.m1()中的synchronized锁定的代码块.必须是在sleep(3000)后才会给变量b加上锁.要想看到锁定b的效果.可以将m1()中的代码修改.
synchronized (this) {
try {
b = 1000;
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("b1 = " + b);
}
这样就无论怎么样都是先.执行完该代码块,包括b变量的使用.
chenjian98 2011-10-08
  • 打赏
  • 举报
回复
Java的对象锁机制规定了被synchronized关键字锁住的代码块和方法,每次只允许一个线程访问其中的共享变量
而你的代码中只有两个线程,主线程和t1,当执行t1.start()方法是,该线程运行,调用run()方法,run()方法再调用m1(),而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程,调用m2(),打印b
而如果让住线程休眠5000毫秒,这时线程t1将先被唤醒,将b修改为1000,然后再执行主线程,最后输入b的结果都是1000
qizaodian 2011-10-08
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sammiriche 的回复:]
引用 2 楼 qizaodian 的回复:

1, m1()中有 sleep(3000) 3000>500, 所以先是执行t.m2(),再执行t.m1()
2, 而把sleep(500)改为sleep(5000)后,执行的顺序就要反过来了,m1()中的变量b被修改了,所以两个输入都是1000
3, m2()是TT类中的成员方法,当然可以调用本类中的变量b
4,代码中的synchroniz……
[/Quote]

首先,代码中的变量b是共享变量,m1()和m2()中被称为临界区代码。
Java的对象锁机制规定了被synchronized关键字锁住的代码块和方法,每次只允许一个线程访问其中的共享变量
而你的代码中只有两个线程,主线程和t1,当执行t1.start()方法是,该线程运行,调用run()方法,run()方法再调用m1(),而m1()你让线程t1休眠了3000毫秒,t1让出来对象锁,所以这时执行主线程,调用m2(),打印b
而如果让住线程休眠5000毫秒,这时线程t1将先被唤醒,将b修改为1000,然后再执行主线程,最后输入b的结果都是1000
烟草味淡淡 2011-10-07
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 qizaodian 的回复:]

1, m1()中有 sleep(3000) 3000>500, 所以先是执行t.m2(),再执行t.m1()
2, 而把sleep(500)改为sleep(5000)后,执行的顺序就要反过来了,m1()中的变量b被修改了,所以两个输入都是1000
3, m2()是TT类中的成员方法,当然可以调用本类中的变量b
4,代码中的synchronized关键字表示改代码块被加锁,在这段代码执行过……
[/Quote]

不好意思理解能力有限
3中说明可以调用本类中的变量b
那此时锁定代码块里面b改变了 m2方法可以用调用?

可是4中说道 在这段代码执行过程中变量b的值外部是不能修改的
请问怎么理解。
qizaodian 2011-10-07
  • 打赏
  • 举报
回复
1, m1()中有 sleep(3000) 3000>500, 所以先是执行t.m2(),再执行t.m1()
2, 而把sleep(500)改为sleep(5000)后,执行的顺序就要反过来了,m1()中的变量b被修改了,所以两个输入都是1000
3, m2()是TT类中的成员方法,当然可以调用本类中的变量b
4,代码中的synchronized关键字表示改代码块被加锁,在这段代码执行过程中变量b的值外部是不能修改的
阳明 to life 2011-10-07
  • 打赏
  • 举报
回复
  public void m2() {
System.out.println("b2 = " + b);
}

改成
  public synchronized void m2() {
System.out.println("b2 = " + b);
}

这样才保证两个方法在同一对象上的同步

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧