发现一个多线程很奇怪的问题,急急急!
老师先看这个图:问题一:我的理解是,这个多线程题分为主线程跟new Thread自己创建的线程(暂且称为副线程),在main方法中运行到t.start这一句开启副线程,顺序先是执行主线程即test.m2();System.out.println(test.b);这两句,在m2方法中把b=2000了,我的理解是m2方法跑完了接着执行System.out.println(test.b);这句,因为这句也是主线程里面的,但是这句话的结果输出的却是1000?为什么呢?这个1000代表着进行完m2之后就把锁给m1就执行m1了,那请问老师正确的执行顺序是什么呢?
问题二:为了验证我上面理解的准确性,我在m2方法中加了一条输出语句,想看b的值,但是结果却是不一定的???
这是说明主线程中的System.out.println(test.b);语句跟m1方法是同步线程吗??但是m1不是加了锁吗?不是应该执行完m1再做其他的吗?为什么会出现呢这样的结果呢??
正在回答
同学你好,
第一个问题,进入main方法线程就会执行
第二个,如果只是这两个方法的对结果的影响,同学这里可以先不考虑主线程,这样可能会搞混。
1)如果m1加锁,m2加锁,它们之间不会同时执行,一定是分开的,同学在之前的测试中也看到了始终是其中一个执行完另一个才执行。也就是同时只能执行一个加了synchronized的方法
2)如果m2不加锁,它们两个是可以同时执行了,可以看到m1和m2之前穿插着执行了,并且你会发现后m2面尽然也输出了1000,这说明m2修改了数据后,m1也执行了。导致出现了脏数据。
所以只有同时加了synchronized的方法不能同时访问,如果有一个没有加,那么
没有加synchronized的方法不受加了synchronized的方法的影响。因此它们之间都加锁数据正常,如果其中一个不加锁可能会出现脏数据。
这里同学就可以先忽略主线程打印的问题。(主线程的打印与上面不是一回事),建议同学慢慢来理解,线程的确是有点不太好理解。
如果我的回答解决了你的疑惑,请采纳,祝学习愉快~
同学你好,
不会给main线程优先分配资源的,它的分配策略是有操作系统决定的。这里只是看起来先给main线程分配的,但是实际上不上的~
首先抢占资源需要有两个线程同时执行才会出现。我们来分析一下m2方法有几个线程执行了,
1) t.start();启动线程,也就是执行run方法中的代码,可以看到这个线程其实只执行了m1这个方法
2)而m2方法只在main线程中执行了,这说明m2方法只在主线程中执行了
3)同学可能会疑问,m1也只在副线程中执行了,为什么他们抢资源了。这里其实是m1(它是一个线程在调度的)需要使用b这个属性,而主线程也需要b这个属性。所以这两个线程出现了谁先获得了cpu,谁就可以操作b的这个属性。这样的资源争夺。
如果我的回答解决了你的疑惑,请采纳,祝学习愉快~
同学你好,
首先来说一下主线程和同学这里所说的副线程,都是线程,其实他们是异步的。
接下来结合同学的结果来解释一下会更好。
1.首先运行了main方法开启了main线程
2.main线程接着往下执行,在t.start();开启了一个副线程。(注意只是开启了,只能说明它具备运行的资格了,但是cpu不一定给他分配了资源)
3.此时程序中有两个线程在等待cpu分配资源。(分配策略有系统决定)
4)此时main线程占有资源,因此继续执行下面的test2.m2();此时b=2000,
5)主线程执行完之后,副线程获得资源开始执行,所以出现了同学看到的,主线程执行完了,m1才执行。其实这里只是争夺资源的问题~所以他们的执行顺序是不一定的。如果项目中的内容比较小,可能会出现一只是一种执行情况的现象
老师在sleep前后都添加了输出,并且在main方法中将b多输出几次,可以看到b的两个值,还看到了线程资源的争夺。(注意这里只是不能同时执行m1和m2)但是两线程并没有同步
休眠时的资源抢占
4. 老师修改后的代码,同学可以用来试一下
package ceshi; public class Test2 implements Runnable { int b=100; public synchronized void m1() throws InterruptedException{ b=1000; System.out.println("m11:"+b); Thread.sleep(5000); System.out.println("m1:"+b); } public synchronized void m2() throws InterruptedException{ b=2000; System.out.println("m21:"+b); Thread.sleep(1000); System.out.println("m2:"+b); } public static void main(String[] args) throws InterruptedException { Test2 test2=new Test2(); Thread t=new Thread(test2); t.start(); test2.m2(); for(int i=0;i<100;i++){ System.out.println("main:"+test2.b); } } public void run() { try { m1(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
如果我的回答解决了你的疑惑,请采纳,祝学习愉快~
相似问题
登录后可查看更多问答,登录/注册
- 参与学习 人
- 提交作业 323 份
- 解答问题 8263 个
本阶段将带你学习主流框架SSM,以及SpringBoot ,打通成为Java工程师的最后一公里!
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星