求各位帮我指点下关于synchrolized锁的问题,真是难死了。

Areaze 2015-11-22 07:08:47
加精
源代码如下
public class TT implements Runnable {
int b = 100;

public synchronized void m1() throws Exception{
//Thread.sleep(2000);
b = 1000;
Thread.sleep(5000);
System.out.println("b = " + b);
}

public synchronized void m2() throws Exception {
Thread.sleep(2500);
b = 2000;
}

public void run() {
try {
m1();
} catch(Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args) throws Exception {
TT tt = new TT();
Thread t = new Thread(tt);
t.start();

tt.m2();
System.out.println(tt.b);
}
}


以上两个方法为同一个对象的两个线程调用的方法,m2被main方法里的主线程调用,m1被子线程调用,两个方法都加锁的时候,请问哪个先被锁呢?是main方法里的主线程先被锁吗?我疑惑的点就是到底这个谁先拿到锁的顺序是怎么分的?是按方法里的语句,还是所有的都是主线程先获得锁?这个问题在马士兵教程里被刻意回避过去了,网上相关资料搜了好久都没有满意的答案,只有去论坛里请教各位了,多谢!
...全文
2646 32 打赏 收藏 转发到动态 举报
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
NothingSerious2811 2016-03-31
  • 打赏
  • 举报
回复
引用 24 楼 endlesstask 的回复:
你只要记住一点synchronized  永远是对对象加锁的,这个lock就是在这个对象上面的,你这样的写法只是保证m1 和 m2 不能同时执行,一个执行完才能执行另外一个,至于先后顺序需要看调度的。不要本末倒置,为了研究执行顺序不了解synchronized  的真正用途
说的对啊,同步锁只是防止一个方法或者对象被同时操作,而没有先后之分的
NothingSerious2811 2016-03-31
  • 打赏
  • 举报
回复
引用 2 楼 a254111623 的回复:
你好,我最近也是刚学习马士兵的java,对于这个问题,我当初也有疑惑,但是我的理解是, t.start()并不是代表进程开始运行,而是进程就绪状态,也就是说如果cpu还没分时间片给这个进程,这个进程是不会开始的,而m2()方法是主进程的,所以我想相对于t进程,主进程优先跑,也就是m2先拿到锁。或许我的理解有误,我也在寻求更能说服力的答案,互相学习吧。
你整个解释的过程全是猜测,这样会误导新人的,知道不
cjx6600115 2016-03-03
  • 打赏
  • 举报
回复
引用 14 楼 hemowolf 的回复:
2楼说得没错 t.start() 只是让线程就绪,不一定马上就运行,因此子线程还是子线程哪个先运行,还说不准 子线程和主线程都对同一个对象加锁,因此两个方法一定不会被打断 搞清这一点,后面的事就简单了
十五楼正解,变量并没有加锁,无论哪个线程先执行,都不会干扰到对b的赋值,并且m1()睡眠时间是5秒,m2()的睡眠时间是2.5秒,如果是按原代码执行程序的话,肯定是要输出2000的.
结贴是美德 2016-02-05
  • 打赏
  • 举报
回复
这个问题很基础呀,看cpu时间片轮转了,这是由操作系统控制的,java无法参与,因此从java的角度来看,谁先谁后是“随机”的。
aqwe 2016-02-04
  • 打赏
  • 举报
回复
public static void main(String[] args) throws Exception { TT tt = new TT(); Thread t = new Thread(tt); t.start(); tt.m2(); System.out.println(tt.b); } 这个main方法存在于jvm内存模型的栈里面。当你执行 t.start();的时候,jvm做的就是新开一个栈,然后把t.start()所需要的属性参数等放入到新开的栈里面,然后两个栈(两个线程)就开始同步执行。在单核情况下先执行哪个就看jvm的调度了,在多核情况下一般来说两个线程是一块执行的。 然后你可以看一下线程的start()方法的源码: if (threadStatus != 0 || this != me) throw new IllegalThreadStateException(); group.add(this); start0(); if (stopBeforeStart) { stop0(throwableFromStop); 上面这一串语句,是和 tt.m2(); 这一个语句一块执行的,先执行哪个可想而知。。。 不出意外的话,肯定是m2先被执行的
qq_21992489 2016-01-26
  • 打赏
  • 举报
回复
像你的这种情况 并没有限制 m1,m2的顺序 你只是限制了 在同时有多个对象 调用m1方法时 其他的对象要等m1 执行完才行 至于m1,m2的顺序纯粹看JVM了。。
bigphp 2015-12-11
  • 打赏
  • 举报
回复

评论一个图,用下地址,,,,,
姓氏弓长张 2015-12-04
  • 打赏
  • 举报
回复
你只要记住一点synchronized  永远是对对象加锁的,这个lock就是在这个对象上面的,你这样的写法只是保证m1 和 m2 不能同时执行,一个执行完才能执行另外一个,至于先后顺序需要看调度的。不要本末倒置,为了研究执行顺序不了解synchronized  的真正用途
qq_33200224 2015-12-04
  • 打赏
  • 举报
回复
好难 并看不懂啊
  • 打赏
  • 举报
回复
谁先获得锁不一定,视线程的调度情况而定
piaopiao11 2015-11-30
  • 打赏
  • 举报
回复
引用 17 楼 xuteng1 的回复:
[quote=引用 12 楼 wpfdh 的回复:] [quote=引用 11 楼 piaopiao11 的回复:] 要想先执行m1 也很简单,在执行tt.m2();前面加一个打印,一般流输出也是比较费时的。 t.start(); System.out.println(111); tt.m2();
原来如此 多谢多谢 果不其然[/quote]
引用 12 楼 wpfdh 的回复:
[quote=引用 11 楼 piaopiao11 的回复:] 要想先执行m1 也很简单,在执行tt.m2();前面加一个打印,一般流输出也是比较费时的。 t.start(); System.out.println(111); tt.m2();
原来如此 多谢多谢 果不其然[/quote] 你可不能信他写的,他教你的是笨方法,那是你机器性能不够好,机器性能好点又是另外的结果,比如你扔到服务器上去,说不定就是先执行M2[/quote] 加一行输出可以让两个线程都有执行的机会,但如果不加这行输出,基本主线程m2必然会先执行。
xuteng1 2015-11-27
  • 打赏
  • 举报
回复
引用 12 楼 wpfdh 的回复:
[quote=引用 11 楼 piaopiao11 的回复:] 要想先执行m1 也很简单,在执行tt.m2();前面加一个打印,一般流输出也是比较费时的。 t.start(); System.out.println(111); tt.m2();
原来如此 多谢多谢 果不其然[/quote]
引用 12 楼 wpfdh 的回复:
[quote=引用 11 楼 piaopiao11 的回复:] 要想先执行m1 也很简单,在执行tt.m2();前面加一个打印,一般流输出也是比较费时的。 t.start(); System.out.println(111); tt.m2();
原来如此 多谢多谢 果不其然[/quote] 你可不能信他写的,他教你的是笨方法,那是你机器性能不够好,机器性能好点又是另外的结果,比如你扔到服务器上去,说不定就是先执行M2
xuteng1 2015-11-27
  • 打赏
  • 举报
回复
这两个是先运行m1还是m2是不确定的,都有可能先运行,cpu先执行m1,执行一会又切到m2线程,有可能m1再start的时候,m2线程已经拿到锁开始赋值了,也有可能m2在start的时候,m1拿到锁赋值,马士兵不会跟你们讲,这个cpu究竟是怎么切的吧,说这段程序有一个固定结果的介意还是再学学多线程
业余草 2015-11-27
  • 打赏
  • 举报
回复
你对线程和synchrolizd还是没有学透!!多看看书!! 谁先被锁,谁先执行,这个都有可能! 你的变量没有加锁,这两个方法互不影响!
CoderToSurvive 2015-11-27
  • 打赏
  • 举报
回复
谁先执行是不一定了 线程start之后并不是等待结果 可以看作是与主线程并行之行 谁先拿到的锁谁就先执行了 因此结果是不定的
花形翼 2015-11-27
  • 打赏
  • 举报
回复
当线程准备启动时,主线程的m2方法已经拿到锁,所以m2执行完后,只线程才拿到锁,在拿到锁的过程中主线程System.out.println(tt.b);这句已经执行了。楼主学习线程建议前后打印出执行时间System.out.println(new Timestamp());好对比看锁
xingbenfeng 2015-11-27
  • 打赏
  • 举报
回复
从多线程的理论角度分析,这个程序的运行结果可能有两种:1. m1先执行,m2再执行; 2.m2先执行,m1再执行。 实际运行结果是哪一种取决于tt.m2()方法和tt的run方法哪个先得到CPU资源。 一旦一个方法先得到了执行机会,就会得到tt对象的锁资源,并且直到执行完成再释放(sleep方法并不释放对象锁资源),这样就导致两个方法中的一个方法只能在另一个方法完成后才得到锁资源进行执行。 所以两个方法实际一定是顺序执行。
u012684688 2015-11-27
  • 打赏
  • 举报
回复
DDDDD
小灰狼 2015-11-26
  • 打赏
  • 举报
回复
2楼说得没错 t.start() 只是让线程就绪,不一定马上就运行,因此子线程还是子线程哪个先运行,还说不准 子线程和主线程都对同一个对象加锁,因此两个方法一定不会被打断 搞清这一点,后面的事就简单了
Areaze 2015-11-23
  • 打赏
  • 举报
回复
引用 3 楼 u011225629 的回复:
关于线程,其实确实是一个难点,至于你所提到的问题下面是我的见解。 首先在解析类的时候,首先会加载主函数,当然main是一个线程整个一个程序是一个进程,首先走主函数,然后通过对象调用去各个其他的线程,而一个被加锁的方法,只有一个对象能够同时调用它,等等,如果想仔细的学习一下线程话,可以查看我的博客,有很多多事讲解线程的博客。希望对你有所帮助。
多谢 我去学习下
加载更多回复(11)

62,614

社区成员

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

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