首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > JAVA > J2SE开发 >

请帮助解释的多线程的执行顺序有关问题,先多谢!synchronized

2013-04-09 
请帮助解释的多线程的执行顺序问题,先谢谢!synchronized请解释下以下线程的执行顺序,并且告诉我下,为什么

请帮助解释的多线程的执行顺序问题,先谢谢!synchronized
请解释下以下线程的执行顺序,并且告诉我下,为什么的理解是错误的:

给出两种执行顺序:
1、
thread.start();进去就绪状态---》调用run()方法,走到m1()--->锁定TT,此时b=1000---》进入休眠5秒状态
在sleep过程中,main方法开始执行,TT由于是锁定状态,则main线程不能调用m2()的方法,只有等待thread线程执行完,5秒过后,thread线程执行完,先打印b=1000 
然后main线程再调用m2()方法,锁定TT,等待2.5秒以后,设置b的值为200,最后打印tt.b的值为2000
最终显示结果为:
b=1000
2000

2、
thread.start();进去就绪状态---》Main线程执行,调用tt.m2(),TT锁定,m2()方法执行完毕以后才能释放锁,释放锁后thread才能执行m1(),m2休眠2.5秒后,设置b=2000,然后先打印tt.b的值为2000,然后释放锁
然后thread执行m1方法,锁定TT,设置b=1000,等待5秒后,打印b=1000
最终显示结果为:
2000
b=1000


我这边实际的执行结果是
1000
b=1000

1、请解释这是何种逻辑?
2、假如把m2的synchronized关键字去掉,有是一种啥效果?怎么执行的呢?

先谢谢大家!


public class TT implements Runnable{
int b=100;
public synchronized void m1() throws Exception{
b=1000;
Thread.sleep(5000);
System.out.println("b="+b);
}
public synchronized void m2() throws Exception{
Thread.sleep(2500);
b=2000;
}

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

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

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

}

[解决办法]
我这边:

有时候打印:
1000
b=1000

有时候打印:
2000
b=1000


[解决办法]
程序由主线程调用,当执行到thread.start()后,创建了一个新的的线程,去执行m1()方法
而主线程继续执行,这个时候m2()方法已经调用了。2.5秒后,这个时候m2()方法执行完毕了,
而m1()方法还没完毕,因此此时的时候b仍然等于1000.所以会先输出1000,然后输出b=1000.

这个跟synchronized没关系吧,没有多个线程同时访问同一个方法啊??
如果不清楚的话,可以把m2()方法里面的暂停去掉,这样的话就是LZ猜测的第二种结果了。
[解决办法]
运行了几次,结果为
1000
b=1000

2000
b=1000
[解决办法]
引用:
程序由主线程调用,当执行到thread.start()后,创建了一个新的的线程,去执行m1()方法
而主线程继续执行,这个时候m2()方法已经调用了。2.5秒后,这个时候m2()方法执行完毕了,
而m1()方法还没完毕,因此此时的时候b仍然等于1000.所以会先输出1000,然后输出b=1000.

m2()方法执行完毕后,b不是应该为2000吗
[解决办法]
以下仅代表个人观点:
    主线程启动了两个线程,由main线程生成了一个thread线程,两个线程虽然没有什么关联关系,但是新线程的启动肯定需要时间,虽然时间很短但是没有main线程直接继续运行来的快,所以是main线程优先进入了m2方法,由于m2方法是synchronized方法,即使thread线程初始化完成了,也要等待锁释放,等main线程的tt.m2();执行完成后,thread线程才可以执行。这时两个线程就并发执行了,如果thread执行的快,就会输出“1000”,否则,就会输出“2000”。但是由于thread线程因为等待了5秒,最后输出的肯定是“b=1000”。
   不知道说的清不清楚?
[解决办法]
其实就一句话:线程同步问题!
    两个线程要是不进行同步,其中指令的执行顺序是不可预期的!
    也就是说:结果可能与你预期相同,也可能不同,同或不同,都属于概率事件!

具体而言:你这里用的synchronized关键字,只保证了两个方法不会同时执行,但却无法保证二者到底谁先执行!

从设计者的角度而言,如果两个事件需要顺序发生,那么一般不会将其分派到两个不同线程中执行!否则,需要的同步机制是比较复杂的。
[解决办法]
你试的不够多
[解决办法]
如果楼主想按顺序来执行的话,可以在run()里面加上m1();m2();或是m2();m1();

像楼主上面的代码那么执行的话,执行结果确实是不可预计的
------解决方案--------------------



public class TT implements Runnable{ int b=100; public synchronized void m1() throws Exception{ b=1000; Thread.sleep(5000); System.out.println("b="+b); } public synchronized void m2() throws Exception{ Thread.sleep(2500); b=2000; } @Override public void run() { try { m1(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args)throws Exception { TT tt = new TT(); Thread thread = new Thread(tt); thread.start(); tt.m2(); System.out.println(tt.b); } } 

楼主你代码的结果是随机的。。。
[解决办法]
main方法开始执行,TT由于是锁定状态

TT并没有加锁,加锁的只是那2个方法所以main不会等待而是直接执行,如果要将整个实例锁住需要对整个对象加锁
[解决办法]

public class Test {
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 50; i++) {
T t = new T();
Thread tt = new Thread(t);
tt.start();
t.m2();/*永远先打印m2  因为  tt.start()创建线程需要分配资源等操作,需要耗时,而t.m2()是顺序执行下来的,所以先执行此方法,会锁住t对象实例,线程tt虽然已经启动但任续等待t.m2()方法释放锁。

呵呵楼主多看下多线程方面的书再多做点练习就熟了*/
}

}
}

class T implements Runnable {

public void m1() throws InterruptedException {
synchronized (this) {
// Thread.sleep(2500);
System.out.println("i'm m1");
}
}

public void m2() throws InterruptedException {
synchronized (this) {
// Thread.sleep(5000);
System.out.println("i'm m2");
}
}

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

[解决办法]
以下仅是个人理解,如有错误请指出:
在这个程序中,程序启动两个线程,一个是main线程,另一个是在main中启动的线程thread.start();,由于这个线程中使用synchronized管住了m1()方法,但注意管理住的只是m1()方法,只能说明这个thread对象在使用的这个方法的时候是互斥使用这个方法,但并不互斥使用m1()方法中的变量,所以在tt.m2();改变了b之后,有可能还是main线程在运行,这时就打印的是2000,如果在tt.m2()改变b之后,由于线程切换,有可能是由thread.start()方法启动的线程在执行,这时这个线程又执行了一次b的赋值,这时两个线程打印的结果都是1000;

热点排行