【Java 并发编程】锁基础

更新的所有的 Java并发编程内容均整理自 《Java 并发编程的艺术》一书, 书中相关内容介绍全面,本文只是对偶觉得有价值和不熟悉的部分进行整理,有兴趣完整系统学习这部分的童鞋请多多购买原书,支持原作者 。

Java 5 之后,新增了 Lock 接口,之前都是靠 synchronized 关键字处理并发的

一、Lock 接口

在 try 语句外加锁, 在 finally 语句中释放锁, 保证锁一定会被释放。

1. Lock vs synchronized

Lock 可以 非阻塞的获取锁、被中断地获取锁、超时获取锁, 这些能力都是 synchronized 不具有的 。

2. Lock 接口 API

Lock 接口共含有以下 API :

  • void lock()
  • lockInterruptibly()
  • tryLock()
  • tryLock(long time, TimeUnit unit)
  • unlock()
  • Condition newCondition()

相关方法描述如下 :

【Java 并发编程】锁基础_第1张图片

二、队列同步器 AQS

AQS 全程 AbstractQueuedSynchronizer , 其是构建锁或者其他同步组件的基础框架,子类继承同步器并实现其抽象方法来管理同步状态,其提供了以下 3 个方法用于更改管理同步状态:

  • getState() 获取当前同步状态
  • setState(int newState) 设置当前同步状态
  • compareAndSetState(int expect,int update) 使用CAS设置当前状态,该方法能够保证状态设置的原子性

相比通过以上,也能看出来,同步器面向的是锁的实现者,其简化了锁的实现方式,屏蔽了底层操作。

我们自定义同步组件时,在其中定义静态内部类,静态内部类继承同步器并且实现独占式获取和释放同步状态,自定义的同步组件通过调用其静态内部类代理实现(将操作代理到该静态内部类上)

1. 同步器提供的可重写的方法

  • 独占式获取同步状态
  • 独占式释放同步状态
  • 共享式获取同步状态 acquireShared(int arg)
  • 共享式释放同步状态 releaseShared(int arg)
  • 当前同步器是否被独占

2. 同步器的实现

  1. 同步队列: 同步器依赖内部的同步队列来完成同步状态的管理
  2. 独占式同步状态获取与释放: 线程获取同步状态失败后进入同步队列中,后续对线程进行中断操作时,线程不会从同步队列中移出

【Java 并发编程】锁基础_第2张图片

  1. 共享式同步状态获取与释放: 共享式获取同一时刻能否有多个线程同时获取到同步状态。以文件的读写为例:写操作要求对资源的独占式访问,而读操作可以是共享式访问。

  2. 独占式超时获取同步状态

三、重入锁 ReentrantLock

  • 支持一个线程对资源的重复加锁
  • 支持获取锁时的公平和非公平性选择 (公平: 先到先得就是公平)

重入
获取锁时增加同步状态值,释放锁时减少同步状态值 (同步状态值为 0, 最终释放)

公平
加入同步队列当前节点是否有前驱节点的判断,如果有前驱节点,则等待

公平 vs 非公平
非公平性锁可能使线程“饥饿”, 但是公平锁具有更大的开销(大量的线程切换),因此非公平锁是默认实现

四、读写锁 ReentrantReadWriteLock

读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升。

1. 使用场景

某个共享资源大部分实现提供读服务,少部分时间进行写操作。

2. 特性

  • 公平性选择
  • 重进入
  • 锁降级: 写锁降级为读锁 —— 锁降级是指把持住写锁,再获取到读锁,随后释放写锁的过程。
    • 为什么支持锁降级: 锁降级是为了保证数据的可见性,如果当前线程不获取读锁而是直接释放写锁,假设此刻另一个线程获取了写锁并修改了数据,那么当前线程无法感知线程T的数据更新。如果当前线程获取读锁,即遵循锁降级的步骤,则线程T将会被阻塞,直到当前线程使用数据并释放读锁之后,另一个才能获取写锁进行数据更新。
    • 为什么不支持锁升级:锁升级是指把持读锁、获取写锁,最后释放读锁的过程。不支持锁升级也是为了保证数据可见性,如果读锁已被多个线程获取,其中任意线程成功获取了写锁并更新了数据,则其更新对其他获取到读锁的线程是不可见的。

3. 使用

  • readLock() —— 获取读锁
  • writeLock() —— 获取写锁

4. 应用

get 操作加读锁, put 操作加写锁,可以使用其实现一个线程安全的 map

你可能感兴趣的:(java,开发语言,jvm)