重入锁、独占锁与共享锁、公平锁与非公平锁

前面了解了J.U.C中两个重要的类或接口,其它的实现类都是以此为基础的,现在还需要了解一下一些锁的概念,有助于后面学习一些实现类或接口。

重入锁

在并发中,无论是synchronized还是lock也好,内部都有重入的特性,而且特性的含义是一样的。

重入(re-entrant),同一个线程可以获取已持有的锁;

已知的有两种出现场景:
1、加锁方法调用另外一个加锁方法;
2、递归调用加锁方法;

归根结底,就是一个加锁方法调用了另外一个加锁方法;

  1. public class ReentrantTest {
  2. public static void main (String[] args) {
  3. new Thread(new TestRunnable()).start();
  4. }
  5. static class TestRunnable implements Runnable {
  6. @Override
  7. public void run () {
  8. Test.say();
  9. }
  10. }
  11. static class Test {
  12. public static synchronized void say() {
  13. dosomething();
  14. }
  15. public static synchronized void dosomething() {
  16. }
  17. }
  18. }

如果synchronized 没有重入特性,执行say方法时线程获取到Test的锁,调用dosomething的时候,再次获取锁,因为没有重入锁特性,导致无法获取到锁,线程就会死锁,这样就会出错。

所以重入锁是为了解决重复获取锁的问题的,线程对象是当前持锁对象。

独占锁与共享锁

独占锁与共享锁,线程对象是多个线程;
独占锁,从名字上就可以知道,一个线程获取了锁,其它线程就不能获取到锁,必须等锁释放了,才能可能获取到锁。

举个例子:

沙漠中有一杯水,有十个旅行者,都想喝水,但是同时只能一个人拿起水杯喝水,一个人喝完,第二个人才能喝水。

共享锁,是可以多个线程获取到锁,但是任何东西都不是无限制的,不是任何线程都可以共享锁。

举个例子:

图书馆里有一本书,各个楼层的书馆室内的电脑,都可以查到这个本书的信息,不是只能一台电脑查完,其它书馆室的电脑才能查询这本数的信息;但是也不是任何电脑都能查询这本数的信息,学生自己带到图书馆的电脑就不能查询书的信息。

后面有一个ReentrantReadWriteLock就是这种锁机制,后面详细学习的时候,再好好了解这个接口。

公平锁与非公平锁

公平锁与非公平锁,对象也是多个线程。

什么是公平?
简而言之,付出多的,应该得到回报,在日常购物排队中,因为排在前面的比排在后面的等的时间长(相邻两个人,前面一个相对与后面一个), 最先结账的应该是排在最前面的。

公平锁,按照上面的逻辑来安排获取锁的话,应该先启动的先获取锁,后启动的后获取锁。

非公平锁,就是不排队,都去结账,谁抢到了位置(获取到锁),谁就去结账(执行代码);

这些逻辑体现在代码上,就是当线程释放了锁,需要从等待线程队列中取出线程用来获取锁的逻辑,是取等待线程中最先启动的,还是都取出来,自由竞争。

总结

了解上面的概念之后,对学习相关的类有很大帮助,对面试也有很大帮助。

转载自


评论


月の守护 2018-08-03 16:31:27
自己给自己加油!
langzi.me 2018-08-03 16:31:27
你是最棒的