synchronized 线程锁问题。求教~(标题要够长,才能有人看)

program___Madman 2009-07-15 10:33:24
public class TestSynchronized implements Runnable {
int a = 100;

public synchronized void show1() {
a = 1000;
try{
Thread.sleep(5000);
}catch(InterruptedException e){}

System.out.println("a = "+a);
}

public void show2(){

try {
Thread.sleep(2500);
a = 2000;
}catch(InterruptedException e){}
}

public void run() {
show1();
}

public static void main(String args[]) {
TestSynchronized ts = new TestSynchronized();
Thread tt = new Thread(ts);
tt.start();
ts.show2();
System.out.println(ts.a);
}
}


这是个简单的小例子,关键就去却与synchronized这个关键字上。我描述下问题。各位大大请看!
这个先是show1方法加了锁。用tt启动线程后,a被赋值成了1000后,show1进入睡眠状态 。主方法里又调用show2的方法。因为show2没有锁,所以a的值最后定位2000;

问题出在这里。
show2 加上了synchronized后。最后的结果都变成了1000.我想问的是~
是某两个方法加锁以后,必须执行完某一个方法,解锁后才能执行另一个有锁的方法吗?这个例题是有两个线程 一个是main的线程,一个是tt 线程。两个线程访问两个加锁的方法。只有一个方法执行完了才能执行另一个吗?
java里只有一个锁吗?
一直没有绕过这个弯,请熟悉的朋友来告诉下。谢谢
...全文
95 11 打赏 收藏 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
program___Madman 2009-07-16
  • 打赏
  • 举报
回复
非常非常感谢~!!!!!长知识了,希望其他迷惘在线程锁的朋友们能看到如此细致的解答
Dan1980 2009-07-16
  • 打赏
  • 举报
回复
synchronized锁定方法的原理是:一个线程要进入一个synchronized修饰的方法,必须事先拿到该方法所属对象的引用(在线程之间可以称为锁),一旦它拿到了,就一直持有这个引用,直到synchronized方法结束才释放。当多个线程同时试图进入一个synchronized方法时,总是有一个线程最先拿到锁并持有它,其它线程因为拿不到锁,所以必须等待。synchronized是Java同步机制中最典型的情况。
program___Madman 2009-07-16
  • 打赏
  • 举报
回复
Dan1980你就像明灯一样指引了我。我清楚了这个执行过程,非常感谢你细致的回答。
请允许我这个新手在提问一下问题,
就是为什么两个线程都等TS的锁呢?为什么TS会有锁?
synchronzied 不是锁了两个方法吗?哪个进程进去就锁定此方法,别的线程无法访问吗?
谢谢
lasfrost 2009-07-16
  • 打赏
  • 举报
回复
show2()是先于show1()执行是因为执行tt.start()后虚拟机需要较长的时间去创建线程,而为什么执行完了show2才执行show1呢,看来只能这么理解,在对方法加synchronized的同时对当前类对象也加了锁,相当于synchronized (this)
Dan1980 2009-07-15
  • 打赏
  • 举报
回复
当show1()是synchronized的、show2()不是的时候,执行的顺序很可能是这样的:

1. 主线程启动;
2. tt线程启动;
3. 主线程执行show2()方法,睡眠2.5秒,未持有任何对象的锁;
4. tt线程拿到ts的锁,执行show1()方法,将a的值修改为1000,并睡眠;
5. 主线程结束睡眠,将a的值修改为2000,同时show2()方法结束,此时a的值是2000;
6. 主线程继续执行main()方法余下部分,打印a的值(此时是2000);
7. tt线程结束睡眠,打印a的值(此时是2000);


当show1()、show2()都是synchronized的时候,执行的顺序很可能是这样的:

1. 主线程启动;
2. tt线程启动;
3. 主线程首先拿到ts的锁,执行show2()方法;
4. 主线程进入show2()方法,睡眠2.5秒,并同时持有ts的锁,此时tt线程由于拿不到ts的锁而被挂起。
5. 主线程结束睡眠,将a的值修改为2000,同时show2()方法结束,主线程释放ts的锁,此时a的值是2000。
6. tt线程被唤醒,拿到ts的锁,将a的值修改为1000,并睡眠。
7. 主线程无需得到ts的锁就继续执行非synchronized部分,打印a的值(此时是1000)。
8. tt线程结束睡眠,打印a的值(此时仍然是1000)。
program___Madman 2009-07-15
  • 打赏
  • 举报
回复
恩,楼上的说的对。可是show2为什么要先执行,并且执行完了,才执行show1呢?
Dan1980 2009-07-15
  • 打赏
  • 举报
回复
很重要的一点:show2()是先于show1()执行的。
program___Madman 2009-07-15
  • 打赏
  • 举报
回复
不一样的,两个不加锁 最后的值是2000 两个同时加锁 值最后是1000;就是两个都加锁这里,搞不清楚执行的过程
windforcecn 2009-07-15
  • 打赏
  • 举报
回复
锁是对对象而言的,你一个main只产生了一个实例,仅对该实例加锁

如果你是static synchronized,则所有的对象都产生锁
lasfrost 2009-07-15
  • 打赏
  • 举报
回复
在你的例程中给show1加synchronized好像没有什么意义。
给某个方法加synchronized意味该方法在任意时刻只能被一个线程执行,其它需要执行该方法的线程需要等待锁。
至于你说的两个线程访问两个加锁的方法跟访问没加锁的方法没什么区别。
synchronized除了用在方法上外还能用在对象上,用法为synchronized (object) {}
jinxfei 2009-07-15
  • 打赏
  • 举报
回复
sleep是不会释放锁的,要释放锁,需要Wait方法。

62,620

社区成员

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

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