public class TT implements Runnable {
int b = 100;
public synchronized void m1() {
b = 1000;
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
Thread.sleep(1000);
b = 2000;
}
public void run() {
m1();
}
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);
}
}
为什么打印出来的是: 1000
b=1000 ?????
int b = 100;
public synchronized void m1() {
b = 1000;
System.out.println("b = " + b);
}
public synchronized void m2() throws Exception {
Thread.sleep(1000);
b = 2000;
}
public void run() {
m1();
}
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);
}
}
为什么打印出来的是: 1000
b=1000 ?????
b = 1000
它是先运行m2方法把b=2000带到main方法中打印b,接着在运行run方法到m1方法中。正常运行模式的结果是:1000
b=1000
它是先运行m2后直接运行run方法接着到m1方法中在到main方法把b打印出来b=1000;
一旦先進入m2,另一個線程就會等待m2方法執行完畢后才會進入m1,而且先啟動m2的可能性還偏大(可能主線程的關係,雖然在後面一句)
所有在main中打印出1000程序也有可能先执行b=2000 main中打印出2000 之后再执行run方法打印出b=1000
原因是m1、m2都是sychronized方法,同一个时刻,只允许一个线程访问一个对象中的一个sychronized方法(例如有线程访问m1的时候,其他线程请求访问该对象的m2也不行)。那么输出的结果就跟线程的推进顺序有关了,主线程时间片没有结束,执行到tt.m2(),此时新建的线程就算执行到run()中访问m1,也会等待主线程执行完了m2,才能够执行m1,结果这两步完了后b还是等于1000.而后是1000 b=1000或者2000 b=1000还是b=1000 1000跟线程的推进执行println的顺序有关,两种结果都是可能的。另一种可能的结果是子线程推进比主线程快,执行到了run中的m1,则会阻塞主线程访问m2,子线程执行完m1后主线程才能访问m2,这时候只有b=1000 2000这种结果。总而言之有1000 b=1000, 2000 b=1000, b=1000 1000,b=1000 2000四种结果。
* CSDN-Thread Synchronized<br>
* 1、注意synchronized的概念<br>
* 1.1、synchronized引入了token概念,要执行methodA\methodB就必须先获得token<br>
* 1.1、同一时间点要么methodA获得token要么methodB获得token<br>
* 2、注意线程的生命周期,Thread.start()并不代表立刻就能得到CPU时间<br>
* 3、这段代码的本质的问题应该是验证标记上synchronized方法的互斥执行
* @version 2012-2-25
*/
public class ThreadSyncA implements Runnable {
/** 标记变量 */
private int bFlag = 100; /**
* methodA
*/
private synchronized void methodA() {
bFlag = 1000;
System.out.println("MethodA==>" + bFlag);
} /**
* methodB<br>
* 1、当前线程先sleep
*/
public synchronized void methodB() {
try {
//即便是线程sleep很长的时间,在没有执行完此方法之前methodA始终没有机会
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
bFlag = 2000;
System.out.println("MethodB==>" + bFlag);
} /**
* {@inheritDoc}
*/
public void run() {
while (true) {
methodA();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} /**
* 测试入口
* @param args 参数列表
*/
public static void main(String[] args) {
ThreadSyncA tsInst = new ThreadSyncA();
Thread threadInst = new Thread(tsInst);
threadInst.start();
//模拟一下等待,确认让methodA早于methodB调用
/*try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
tsInst.methodB();
}
}