很多同学写这个代码时容易写迷糊。其实只要经过下面几个步骤的分析,你会发现这个问题很简单。
1 理清循环50次和子线程运行10次,主线程运行100次,不要交叉在一起
循环50次可以看作是调用方操作,调用方可以选择操作50次,也可以选择操作100次。
子线程和主线程可以看作被调用方接口,调用方只要调用我了,我就执行xxx次(子线程运行10次,主线程运行100次)。
2 注意一点:
子线程运行第一个十次完成前,主线程是不允许运行的,且子线程也不允许运行第二个十次操作。例:调用方第一次调用时,子线程第一个十次调用运行到了第8次。这时子线程持有锁,主线程是进不来的,但是子线程是可以进来的,这就导致如果不做处理,调用方调用子线程进行第二个十次运行,子线程的第一次十次运行和第二次十次运行混在一起,需要怎么处理呢?答案是线程通信。可以使用wait(),notify(),也可以使用java.util.concurrent.locks.Condition。
有了上面的清晰思路代码就好写了。
3 重入锁
为什么子线程的第一次十次运行和第二次十次运行混在一起?第一个十次运行的锁为什么可以第二个十次仍然可以执行?
synchronized可重入性
同一线程在调用自己类中其他synchronized方法/块或调用父类的synchronized方法/块都不会阻碍该线程的执行,就是说同一线程对同一个对象锁是可重入的,而且同一个线程可以获取同一把锁多次,也就是可以多次重入。点击打开链接。
重入锁
(1)重进入:
1.定义:重进入是指任意线程在获取到锁之后,再次获取该锁而不会被该锁所阻塞。关联一个线程持有者+计数器,重入意味着锁操作的颗粒度为“线程”。
2.需要解决两个问题:
线程再次获取锁:锁需要识别获取锁的现场是否为当前占据锁的线程,如果是,则再次成功获取;
锁的最终释放:线程重复n次获取锁,随后在第n次释放该锁后,其他线程能够获取该锁。要求对锁对于获取进行次数的自增,计数器对当前锁被重复获取的次数进行统计,当锁被释放的时候,计数器自减,当计数器值为0时,表示锁成功释放。
3.重入锁实现重入性:每个锁关联一个线程持有者和计数器,当计数器为0时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为0,则释放该锁
下篇:http://blog.csdn.net/wabiaozia/article/details/79534560