Java并发基础(八)-locks包

来源:互联网 发布:淘宝网商城女童鞋 编辑:程序博客网 时间:2024/06/14 09:53

1. 前言

Java锁的种类 java中的锁种类是真的多。而locks包下也有一些。包结构如下:
这里写图片描述

  • AbstractOwnableSynchronizer 一个线程拥有的同步器,这个类提供了创建锁和相关同步器的基础
  • AbstractQueuedLongSynchronizer 所有的同步状态都是用long变量来维护的,而不是int,在需要64位的属性来表示状态的时候会很有用
  • AbstractQueuedSynchronizer 为实现依赖于先进先出队列的阻塞锁和相关同步器(信号量、事件等等)提供的一个框架,它依靠int值来表示状态
  • Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set (wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用。这个是被绑定在Lock上一起使用的。
  • Lock 实现了比synchronized更多的功能,需要注意的是,为了确保可以释放锁,需要在finally语句块中unlock。
  • LockSupport LockSupport是用来创建锁和其他同步类的基本线程阻塞原语。LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到“Thread.suspend 和 Thread.resume所可能引发的死锁”问题。
  • ReadWriteLock 读写锁,读和写是互斥的,多个读锁不互斥,也就是说,在读的时候,不能写,在写的时候,不能读,但是在读的时候可以有多个线程同时读。
  • ReentrantLock 可重入锁
  • ReentrantReadWriteLock 可重入读写锁
  • StampedLock Java 1.8提供了一种读写锁,

2. Condition

Condition是和Lock绑定使用的。Lock#newCondition方法返回一个Condition。
使用方法如下:

  • 创建Lock
  • Lock#newCondition 返回新的Condition (可以多次调用)
  • Condition#await 会导致线程挂起直到signalled,或者中断。
  • Condition#signal 唤醒线程

ArrayBlockingQueue中有大量这样的用法。如图:
这里写图片描述

3. LockSupport

  • park方法能将阻塞线程或者
  • unpark 方法唤醒线程

4. ReentrantReadWriteLock

ReentrantReadWriteLock是locks包中提供的读写锁的一种实现,用法也很简单。一般用jdk提供的ReentrantReadWriteLock。

用法如下

  • 初始化
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();Lock readLock = readWriteLock.readLock();Lock writeLock = readWriteLock.writeLock();
  • 在需要读的时候readLock.lock(),用完之后readLock.unlock()
  • 在需要写的时候writeLock.lock(),用完之后writeLock.unlock()

ReentrantReadWriteLock支持锁降级

什么是锁降级呢。从读写角度来看,写的级别是高于读的。咱们看例子

    public static void main(String[] args){        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();        final Lock readLock = readWriteLock.readLock();        final Lock writeLock = readWriteLock.writeLock();        // 读        readLock.lock();        System.err.println("我是读锁");        // 写        writeLock.lock();        System.err.println("我是写锁");    }

很明显,由于不支持锁升级,因此,会阻塞。输出结果如下
这里写图片描述

我们上面读写翻个顺序。

        // 写        writeLock.lock();        System.err.println("我是写锁");        // 读        readLock.lock();        System.err.println("我是读锁");

输出结果如下:
这里写图片描述

锁降级,将写入锁降级为读锁(很好理解,就像写权限要高于读权限一样)

5. ReentrantLock

也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响

这种锁在ArrayBlockingQueue中有用到。
这里写图片描述

关于用法这里就不说了。
ReentrantLock可是实现公平锁

    public ReentrantLock(boolean fair) {        sync = fair ? new FairSync() : new NonfairSync();    }

从构造函数中来看,是支持公平锁的。

公平锁,等待时间长的优先获得锁。

6. StampedLock

这里想的半天,还是觉得参考资料里面写的很完美,所以,我就不献丑了。大家去看看吧。


参考资料

  • Java锁的种类以及辨析
  • Java 8新特性探究(十):StampedLock将是解决同步问题的新宠
1 0