java synchronized方法中的Thread.sleep()问题

qq_31376151 2018-03-20 05:29:00
今天学习多线程,知道了不同方法使用synchronized只要拥有相同的对象监视器,只允许一个线程访问。于是我测试了一下:

public class Test {
V v = new V();
public void go() {
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
v.f1();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
v.f2();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
v.f3();
}
}
}).start();
}

public static void main(String[] args) {
Test t = new Test();
t.go();
}
class V {
public synchronized void f1() {
System.out.println("method1");
}
public synchronized void f2() {
System.out.println("method2");
}

public synchronized void f3() {
System.out.println("method3");
}
}
}

多次运行结果为同一个:
method1
method1
method1
method1
method1
method2
method2
method2
method2
method2
method3
method3
method3
method3
method3
没问题,加锁的方法只有当前线程运行结束后才会运行下一个。
但我在方法f1();中休眠0.5秒,即:

public synchronized void f1() {
System.out.println("method1");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

运行结果:
method1
method1
method3
method3
method3
method3
method3
method2
method2
method2
method2
method2
method1
method1
method1
并且运行结果不一定相同。
使用了synchronized的方法为什么在使用了sleep之后当前线程退出了,既然退出为什么不在第一个mehtod1输出完后执行别的线程?还是我的理解有错,希望加以指正,谢谢!
...全文
966 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
SwordRed 2019-03-18
  • 打赏
  • 举报
回复
sleep()当然不会退出同步锁,但是每次循环调用同步方法,总是重新获得同步锁。如果超过时间片了,第一个还没执行完,就由剩下两个线程抢CPU调度,顺序就不一定了。
但是,为什么第一个它总是顺序不变,难道线程start()的顺序对CPU第一次调度有影响?
-_-活在当下 2018-12-21
  • 打赏
  • 举报
回复
实际运行顺序没有任何变化,cpu分片执行的,sleep的线程只是等待时间内,其他线程已经执行完了!
qq_31376151 2018-03-23
  • 打赏
  • 举报
回复
引用 3 楼 qq_31376151 的回复:
[quote=引用 2 楼 aachen0 的回复:] sleep不会使当前线程退出同步代码块,谈何其他线程乘虚而入?
是我表达的不清楚,之所以method2和method3会一口气打印出来是因为他们的线程获取到cpu执行权限后在一个时间片内可以执行数次,这里就不存在竞争关系,method1可以先执行一次,也可以先执行两次,甚至m1-m4一同输出,我认为是sleep休眠0.5秒过长,已经远远超过了一个时间片,当f1方法结束后,线程会重新竞争,导致method1不一同输出。这仅仅是我自己思考的,如果有错误请向我指出,谢谢。[/quote] 又说了歧义的话了,我说的不存在竞争关系是线程本身在一个时间片内不存在竞争关系,不同线程一定会有竞争的。
qq_31376151 2018-03-23
  • 打赏
  • 举报
回复
引用 2 楼 aachen0 的回复:
sleep不会使当前线程退出同步代码块,谈何其他线程乘虚而入?
是我表达的不清楚,之所以method2和method3会一口气打印出来是因为他们的线程获取到cpu执行权限后在一个时间片内可以执行数次,这里就不存在竞争关系,method1可以先执行一次,也可以先执行两次,甚至m1-m4一同输出,我认为是sleep休眠0.5秒过长,已经远远超过了一个时间片,当f1方法结束后,线程会重新竞争,导致method1不一同输出。这仅仅是我自己思考的,如果有错误请向我指出,谢谢。
aachen0 2018-03-22
  • 打赏
  • 举报
回复
sleep不会使当前线程退出同步代码块,谈何其他线程乘虚而入?
qq_31376151 2018-03-21
  • 打赏
  • 举报
回复 1
唉,自问自答吧。昨天又想了想,总算想明白了。使用synchronized锁住当前对象的方法的确只允许一个线程运行,造成上面代码结果的原因是循环是写在run方法里的,循环调用的是加锁的方法,第一次循环结束后,f1()方法也执行结束,三个线程会重新抢占资源。但由于cpu有时间片的概念,在一个时间片线程会执行数次,因此打印会一同输出一样的。使用sleep休眠线程1由于休眠时间较长,可能会导致其他线程趁虚而入,所以最后打印的结果不尽相同。

51,396

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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