本帖最后由 王振 于 2012-11-9 11:53 编辑
首先看为什么在method上加同步不能实现你要的结果:
- class sFirstThread implements Runnable
- {
- private int i;
- public void run()
- {
- method();
- }
- public synchronized void method()
- {
- for(; i<1000; i++)
- {
- System.out.println(Thread.currentThread().getName()+"+"+i);
- }
- }
- }
复制代码 1、这里你在run()方法中调用了一个加锁的方法method()。然后在测试类的主方法中启动了两个线程,
相当于创建了两个线程对象(没有名字,你直接使用了),为了便于解释,这里假设两个线程分别是t1,t2,与之相关的sFirstThread 对象分别为s1,12。
2、对于普通加锁的方法,锁就是this,即调用该方法的对象就是该方法的锁。很明显,2个线程你调用了2次该方法,第一次调用时用到的锁是s1,第二次用到的锁是s2。
由于它们使用的是不同的锁,因此就相当于是两个完全不相干的线程在执行,谁抢到执行权谁就执行。
因此谁先执行谁后执行是随机的。
然后再来看在run()中加锁为什么能实现一个线程先打印完,另一个线程才开始继续打印:- class sFirstThread implements Runnable
- {
- private int i;
- public void run()
- {
- synchronized(sFirstThread.class){
- method();
- }
- }
- public synchronized void method()
- {
- for(; i<1000; i++)
- {
- System.out.println(Thread.currentThread().getName()+"+"+i);
- }
- }
- }
复制代码 1、这里你在run()方法中添加了一个同步代码块,锁是sFirstThread.class ,然后将method()方法放到了同步代码块中。
2、你要搞清楚一个问题,程序中为什么要用到同步代码块?是不是想让代码块中的代码作为一个不可分割的整体?要么不执行,只要执行就要全部执行完毕。
3、你把for循环打印的过程放到了同步代码块中,它要么没有得到锁,不执行,要么就是得到锁,执行完毕。
4、又由于两个线程的锁都是sFirstThread.class,因此实现了同步。
备注:method()方法是否加synchronized 效果都一样,这里的同步不是靠它。
如果你对上面讲的第2条不太理解什么意思的话,可以看下面的这个例子:- while(true) {
- if(count > 0) {
- System.out.println("这是" + getName() + ",现在卖出的是第" + (count--) + "张票。");
- }
- }
复制代码 一开始学多线程一般是举这样的例子,因为不能保证if判断和里面的打印语句作为一个整体执行,所以才提出了同步的概念,
也正是由于加同步代码块,才保证了执行完if判断,肯定会紧接着执行打印语句。
跟这个做对比,把if化成for,不是一个道理吗?
|