import java.util.*;
public class TT implements Runnable{
public int i =100;
public synchronized void m1(){
i=1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
public void m2(){
i=2000;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
m1();
}
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
tt.m2();
}
}
说出输出什么,为什么。
public class TT implements Runnable{
public int i =100;
public synchronized void m1(){
i=1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
public void m2(){
i=2000;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
m1();
}
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
tt.m2();
}
}
说出输出什么,为什么。
然后执行 m2 输出 2000 然后睡眠2500 当m2 输出玩再执行时 由于 m1 还在睡眠中 M2 又执行了一边
TT tt = new TT();
tt.m2();
}你试着把main改成这样,看看结果就知道了
先运行Main 主线程 TT tt = new TT();Thread tr=new Thread(tt);定义一个Thread类
然后调用tr.staart()实际上是执行了run(),在run()里面有m1()方法,产生结果i=1000
至于tt.m2();没有结果输出
因为在调用m2方法的时候,资源i还在被线程tr控制着,后边的i=2000的赋值语句不会起作用。
个人观点仅供参考
public synchronized void m1(){
m1被同步当线程在调用m1时i无法被m2访问
在m1里面 i被赋值1000再打印所以一直输出1000
那你把m2中的Thread.sleep(2500),放在i=2000前面,再看看输出??
情况不是这样的。 我已经知道大概情况了,但还有点疑惑,来点权威的点评。
但实际运行肯定是1000。
public class TT implements Runnable{
public int i =100;
public synchronized void m1(){
i=1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i="+i);
}
public void m2(){
//此处改了顺序
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
i=2000;
}
@Override
public void run() {
m1();
}
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
tt.m2();
}
}
被你们搞晕了,每一个线程都有自己独立的内存空间,互不干扰。当你创建一个新线程的时候,本线程中实例变量的变动与其他线程无关。
package test;public class TT implements Runnable {
public int i = 100; public synchronized void m1() {
System.out.println("m1");
i = 1000;
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("i=" + i);
} public void m2() {
// 此处改了顺序
System.out.println("m2");
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
i = 2000;
} public void run() {
m1();
} public static void main(String[] args) {
TT tt = new TT();
Thread tr = new Thread(tt);
tr.start();
tt.m2(); }
}
比较认同8L的看法,因为在调用tr.start()方法的时候,资源i还在被线程tr控制着,后边的i=2000的赋值语句不会起作用。
参照运行后的结束,我的理解是这样的:
Test_Thread tt = new Test_Thread();
Thread tr=new Thread(tt);
tr.start();
tt.m2();这里,Test_Thread tt = new Test_Thread();
Thread tr=new Thread(tt);
tr.start();
因为是多线程运行,所以要考虑哪个建筑第一时间取得cpu,所以要分两种情况:(1)tr.start()先开始:
先新建了一个线程tr,并启动它,tr.start()调用的是tr的run()方法,也就是新建Test_Thread的run()方法
调用m1(),将i付值为1000,然后tr线程挂起,m1()用synchronized修饰,数据i在方法m1()中使用,所以i被锁,
再调用tt.m2(), i=2000;这里访问了受保护资源,付值失败,i仍为1000,然后tt线程挂起,
2500ms后,tt休眠时间到,i仍为1000,tt线程结束,
5000ms后,tr休眠时间到,i仍为1000,tr线程结束.(2)tt.m2()先开始:
将i付值为2000,然后tt挂起,此时i值为2000,
tr.start()启动,m2()没有对i进行保护(加锁),所以m1()可以修改i的值,将i设置为1000,并保护加锁,然后挂起,
2500ms后,tt休眠时间到,i被m1()设置为1000,tt线程结束,
5000ms后,tr休眠时间到,i为1000,tr线程结束.所以楼主的这个程序,应该是输出1000,1000/2000,1000
如果你在 public void m2(){
i=2000;
try {
Thread.sleep(2500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}这段代码的catch语句块中在写一句“System.out.println(i);",那输出结果就会变成:
1000
i=1000;
你这段代码应该是尚学堂马士兵老师JAVA视频上的例题吧,如果不是的话,我建议你到网上下一些马老师的视频看看,它上面就有这样的例子!相信你一定可以懂的!这里我就不罗嗦了!
1.首先,synchronized关键字不管加在类声明上还是加在方法声明上,它所作的工作只是锁定对象,而对于其内部的方法和变量不做“私有”锁定.也就是同一对象就算有synchronized但是其中同一变量还是能被对象中不同方法访问.
2.接下来看楼主提出的问题,从main开始,到tr线程start(),此时开始有tr线程和main线程同步执行,在楼主的程序中,线程执行先被main抢占,执行完i=2000,然后main开始sleep()挂起,tr线程执行i=1000,然后sleep()到结束.tr线程执行最后打印i=1000.至于为什么先执行的是main线程中的i赋值,这是jvm内部机制决定的,在此不做探讨.
3.下面问题的重点来了,究竟synchronized有没有锁定i.楼主可以用下面这段代码测试下:
public static void main(String [] args){
TT tt = new TT();
Thread tr=new Thread(tt);
tr.start();
System.out.println("1");
tt.m2();
}
在tt.m2()执行之前执行一个额外的方法.此时线程的调用过程变为:
(1)System.out.println("1");被首先执行,main线程时间片使用完毕
(2)tr线程开始执行i=1000,开始sleep()休眠(注意,此时tr线程并未结束,synchronized仍旧锁定对象).
(3)main线程执行tt.m2(),i=2000赋值成功,开始休眠(若是i被锁定,m2此时不应该能访问)
(4)tr休眠结束(应该说是m2()休眠先结束,没影响),执行打印方法.综上,如前所述,解释了楼主提出的问题.而后面提出的测试代码的分析就是楼主第二个问题的答案:
因为m2()中先进行休眠,tr线程中首先赋值i=1000然后休眠,在tr休眠未结束之前m2()被唤醒执行i=2000,所以tr线程执行到打印方法时i的值已经为2000了.另外,楼上很多人说的synchronized锁定的是对象内部的变量或方法的说法是不正确的.
详细解释一下吧。
首先,这个问题和synchronized无关。你的synchronized又没有锁变量,这里也不是2个线程调m1,所以synchronized是没影响的。
这个和sleep时间也没有关系。就是主线程的tt.m2()和tr谁先谁后,输出后执行里的那个赋值。
你在tr.start();和tt.m2();之间加上Thread.sleep(1);模拟主线程被阻隔的效果,就输出2000了。
16楼的代码,和我在tr.start();和tt.m2();之间加上Thread.sleep(1);本质相同,都是让m2方法赋值语句晚一点执行,具体说就是在m1线程sleep的时候执行。
tr.start(); 调用了run() ----m1()sleep(5000)
这时调用了m2() 给i重新赋值为2000
tt.m2();坑定100%比m1()先执行。
我觉得这可能是因为tt.m2()属于main,而主线程优先级尤其高的关系。所以绝对是输出1000
16的代码在tt.m2()中将i的赋值语句置于sleep之后了,所以为m1()争取了时间ps:和synchronized 无关