导图社区 Java的并发
这是一篇关于Java的并发的思维导图,包括锁的实现、无锁技术、锁的最佳实践、锁类型、并发工具类等内容。
编辑于2021-09-06 10:26:50Java的并发
锁的实现
synchronized
可以作用在
方法
子类继承方法后默认是不带synchronized, 需要显式声明
static方法 public static synchronized method(){}
类锁
非static方法 public synchronized mithod(){}
对象锁
代码块 synchronized {}
类 synchronized(Clazz.class){}
缺陷
阻塞无法中断
阻塞无法控制超时(无法自动解锁)
无法异步处理锁(不能立即知道是否可以拿到锁)
无法根据条件灵活的加锁解锁(不能修改范围)
当多个线程同时读时也会相互阻塞
Lock
实现类
ReentrantLock
ReentrantReadWriteLock
特点
使用方式更灵活可控
性能开销小
支持中断
支持超时
支持非阻塞获取锁
常用方法
void lock();
获取锁
void lockInterruptibly() throws InterruptedException;
获取锁,可以响应中断
boolean tryLock();
尝试获取锁
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
尝试在给定时间内获取锁
void unlock();
释放锁
Condition newCondition();
新增一个绑定到当前锁的条件
void await() throw InterruptedException;
void awaitUninterruptibly();
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
等待信号
void signal();
void signalAll();
给等待线程发送唤醒信号
Lock readLock();
获取读锁,共享锁
Lock writeLock();
获取写锁,独占锁
工具类
LockSupport
public static void park();
public static void parkNanos(long nanos);
public static void parkUntil(long deadline);
public static void part(Object blocker);
public static void parkNanos(Object blocker, long nanos);
public static void parkUntil(Object blocker, long deadline);
暂停当前线程
public static void unpark(Thread thead);
恢复当前线程
public static Object getBlocker(Thread t);
拿到指定线程的锁的对象
无锁技术
Unsafe API
CAS(CompareAndSwap)
CPU硬件指令支持
CAS指令
Value的可见性
volatile关键字
原子类
AtomicBoolean
AtomicInteger
AtomicIntegerArray
AtomicIntegerFieldUpdater
AtomicLong
AtomicLongArray
AtomicLongFieldUpdater
AtomicMarkableReference
AtomicReference
AtomicReferenceArray
AtomicReferenceFieldUpdater
AtmoicStampedReference
DoubleAccumulator
DoubleAdder
LongAccumulator
LongAdder
Striped64
并发工具类
AQS(AbstractQueuedSynchronizer)
队列同步器,他是构件锁或者其他同步组件的基础
Semaphore
public Semaphore(int permits);
permits:总数
public Semaphore(int permits, boolean fair);
permits:总数 fair:是否是公平锁
public void acquireUninterruptibly();
获取锁
public void release();
释放锁
CountDownLatch
public CountDownLatch(int count);
count:总数
void await() throws InterruptedException;
等待 数量为0
boolean await(long timeout, TimeUnit unit);
限时等待
void countDown();
等待数-1
long getCount();
返回等待数量
与CyclicBarrier做比较
在主线程里await阻塞并做聚合
N个线程执行了countDown,主线程继续
主线程里拿到同步点
基于AQS实现,state为count,递减到0
不可以复用
CyclicBarrier
public CyclicBarrier(int parties);
parties:需要等待的数量
public CyclicBarrier(int parties, Runnable barrierAction);
parties:需要等待的数量 barrierAction:需要执行的任务
int await() throws InterruptedException, BrokenBarrierException;
等待全部线程到达
int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException;
限时等待线程到达
void reset();
重新开始
与CountDownLatch比较
直接在各个子线程里await阻塞,回调聚合
N个线程执行了await时,N个线程继续
回调被最后到达同步点的线程执行
基于可重入锁condition.await/signalAll实现
计数为0时重置为N,可以复用
ThreadLocal
锁的最佳实践
永远只在更新对象的成员变量时加锁
永远只在访问可变的成员变量时加锁
永远不在调用其他对象的方法时加锁
锁类型
可重入锁
synchronized和Lock都是可重入锁
可中断锁
synchronized是不可中断锁 Lock是可中断锁
公平锁
synchronized是非公平锁 Lock默认是非公平锁,可设置
读写锁
Lock
读锁与读锁不互斥 读锁与写锁互斥 写锁与写锁互斥
synchronized
都互斥
自旋锁
偏向锁
偏向锁是无锁竞争下可重入锁的简单实现
优点
加锁和解锁不需要额外消耗,和执行非同步方法比仅存在纳秒级的差距
缺点
如果线程间存在锁竞争,会带来额外的锁撤销的消耗
适用场景
适用于只有一个线程访问同步块
轻量级锁
优点
竞争线程不会阻塞,提高了程序的相应速度
缺点
如果始终得不到锁竞争的线程使用自旋会消耗CPU
适用场景
追求响应时间 同步块执行速度非常快
重量级锁
优点
线程竞争不适用自旋,不会消耗CPU
缺点
线程阻塞,响应时间缓慢
适用场景
追求吞吐量 同步块执行速度较长
分段锁
java.util.concurrent
锁机制类 Locks
Lock
Condition
ReentrantLock
ReadWriteLock
LockSupport
原子操作类 Atomic
AtomicInteger
AtomicLong
LongAdder
线程池相关类 Executor
Future
Callable
Executor
ExecutorService
信号量三组工具类 Tools
CountDownLatch
CyclicBarrier
Semaphore
并发集合类 Collections
CopyOnWriteArrayList
ConcurrentMap