源码如下:
public class TestThread implements Runnable{
int b =100 ;
public synchronized void m1() throws InterruptedException{
b=1000;
Thread.sleep(5000);
System.out.println("m1(): b="+b);
}
public synchronized void m2() throws InterruptedException{
Thread.sleep(2500);
System.out.println("-------------");
b=2000;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
m1();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
TestThread tr = new TestThread();
Thread tt = new Thread(tr);
tt.start();
tr.m2();
System.out.println("主线程 : b="+tr.b);
// Thread.sleep(1000);
// System.out.println("主线程 : b="+tr.b);
Thread.sleep(10000);
System.out.println("最后结果 : b="+tr.b);
}
}
运行结果:
-------------
主线程 : b=1000
m1(): b=1000
最后结果 : b=1000
这里不明白的是, synchronized的作用不是不同线程只能在同一个对象上加一把锁么?既然一个对象只能有一把锁的话, 那用两个synchronized方法同步访问还是有问题,还不如直接把对象给锁住呢
public class TestThread implements Runnable{
int b =100 ;
public synchronized void m1() throws InterruptedException{
b=1000;
Thread.sleep(5000);
System.out.println("m1(): b="+b);
}
public synchronized void m2() throws InterruptedException{
Thread.sleep(2500);
System.out.println("-------------");
b=2000;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
m1();
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
TestThread tr = new TestThread();
Thread tt = new Thread(tr);
tt.start();
tr.m2();
System.out.println("主线程 : b="+tr.b);
// Thread.sleep(1000);
// System.out.println("主线程 : b="+tr.b);
Thread.sleep(10000);
System.out.println("最后结果 : b="+tr.b);
}
}
运行结果:
-------------
主线程 : b=1000
m1(): b=1000
最后结果 : b=1000
这里不明白的是, synchronized的作用不是不同线程只能在同一个对象上加一把锁么?既然一个对象只能有一把锁的话, 那用两个synchronized方法同步访问还是有问题,还不如直接把对象给锁住呢
解决方案 »
- 如何使多个timer在同时执行时不进行并发执行而是进入某个队列进行执行
- 关于Class.forName、Class.class(属性)、getClass()的问题
- 把一字符串转换为十六进制表示后,怎么还原为字符串?(具体程序)
- 大家讨论一下finally 和 try里的 return 的先后问题,我看了很多答案都错误
- Java初学者遇到的极简单的问题
- 使用org.apache.commons.compress 压缩zip包读取时读不到size
- 给出好的建议的,必有重谢
- 感谢你的回复,能否写得更详细些,我的水平的确很菜
- 如何用java读取初始化文件(.ini)
- 关于数组的问题希望大牛给小白解答一下
- Unable to instantiate default tuplizer
- Java Swing 关于菜单过长的问题
-------------
主线程 : b=1000
m1(): b=1000
最后结果 : b=1000
那分析下执行的顺序:
1. 先是主线程m2()方法执行完"------------------"并将b值由100改为2000,然后时间片结束。
2. 执行线程2的m1()方法将b值由2000改为1000, 然后回到主线程。
3. 执行主线程的 System.out.println("主线程 : b="+tr.b), 得到 主线程 : b=1000
4. 然后继续执行线程2的m1()方法, 打印 m1(): b=1000
5. 最后执行主线程,打印 最后结果 : b=1000
应该是这样的执行结果, 但是我有一个疑问, 这样由CPU进行线程间的切换的话, 由于m1()和m2()方法都加了锁,那这两个方法在执行的时候tr这个对象应该是被锁住了啊, 既然是锁住的话,那么如果CPU从一个线程对象切换到另外一个线程对象,用的是同一个TestThread对象, 难道不会重复的加锁么? 比如从主线程的m2()切换到线程2的m1(), 那主线程的m2()加在tr上的锁怎么办? 请指教.
再执行的m1()
tt.start(); 不会马上执行线程,只是放线程池中等待CUP来调度。
先执行的tr.m2();取得对象锁
当tr.m2();执行完成后,m1()取得锁执行。
所以结果都是b=1000
意思可以说,我要用tr,得先拿到tr的锁(或者说是钥匙),才能使用。所以怎么可能会重复加锁呢,锁(钥匙)只有一个,谁拿在手里,谁先用,用完归还,没拿到的线程就等待。线程2没有获取到tr对象锁,他会等待直到主线程从m2()方法执行返回tr锁,然后再获取tr对象锁。
意思是说, 只要执行tr的使用了sychronized关键字的方法,tr对象上就会有锁,无论哪个线程执行都需要获得该锁的钥匙么?
汗 m2执行完 不是释放锁了