读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。
欢迎star、fork,读书笔记系列会同步更新
git
module
j360-jdk-thread/me.j360.jdk.concurrent
本书前三章分别为
并发编程的挑战,也就是并发编程的缘由所在
底层的实现原理
java内存模型
分别从cpu x86,x64以及内存模型等概念中描述java对并发编程的实现和控制,概念较为底层和基础,读书笔记略过前三章直接从第四章应用实现及原理基础开始。
章节
并发编程基础
java中的锁
并发容器和框架(重点)
13个操作原子类
java并发工具类
线程池
Execurot框架
内容
java中的锁
Lock接口
Lock接口出现之前,java是通过synchronized关键字实现的锁功能,javase5之后,并发包新增了Lock接口
Lock使用方式,和分布式锁的构造很像。
Lock lock = new ReentrantLock
lock.lock();
try{
}finally{
lock.unlock();
}
Lock接口提供了Synchronized关键字不具备的特性
尝试非阻塞地获取锁
当前线程尝试获取锁,没有其他线程获取锁,则成功
能被中断的获取锁
超时获取锁
在指定的时间内获取锁
Lock接口的API
void lock()
void lockInterruptibly() throws InterruptedException
boolean tryLock()
boolean tryLock(long time,TimeUtil unit) throws InterruptedException
void unlock()
Condition newCondition
获取等待通知组件,该组件和当前的锁绑定,当前线程只有获取了锁,才能调用该组件的wait()方法,而调用后,当前线程将会释放锁
队列同步器
锁的实现基于队列同步器完成,AbstractQueuedSynchronized(简称同步器),使用一个int成员变量表示同步状态,通过内置的FIFO队列来完成资源获取线程的排队工作
public class ReentrantLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = 7373984872572414699L;
/** Synchronizer providing all implementation mechanics */
private final Sync sync;
/**
* Base of synchronization control for this lock. Subclassed
* into fair and nonfair versions below. Uses AQS state to
* represent the number of holds on the lock.
在这里!!!
*/
abstract static class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -5179523762034025860L;
/**
* Performs {@link Lock#lock}. The main reason for subclassing
* is to allow fast path for nonfair version.
*/
abstract void lock();
/**
* Performs non-fair tryLock. tryAcquire is
* implemented in subclasses, but both need nonfair
* try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
protected final boolean isHeldExclusively() {
// While we must in general read state before owner,
// we don't need to do so to check if current thread is owner
return getExclusiveOwnerThread() == Thread.currentThread();
}
final ConditionObject newCondition() {
return new ConditionObject();
}
// Methods relayed from outer class
final Thread getOwner() {
return getState() == 0 ? null : getExclusiveOwnerThread();
}
final int getHoldCount() {
return isHeldExclusively() ? getState() : 0;
}
final boolean isLocked() {
return getState() != 0;
}
/**
* Reconstitutes this lock instance from a stream.
* @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
setState(0); // reset to unlocked state
}
}
/**
* Sync object for non-fair locks
非公平锁
*/
static final class NonfairSync extends Sync {
private static final long serialVersionUID = 7316153563782823691L;
/**
* Performs lock. Try immediate barge, backing up to normal
* acquire on failure.
*/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
}
/**
* Sync object for fair locks
公平锁
*/
static final class FairSync extends Sync {
private static final long serialVersionUID = -3000897897090466540L;
final void lock() {
acquire(1);
}
/**
* Fair version of tryAcquire. Don't grant access unless
* recursive call or no waiters or is first.
*/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
重入锁 ReetrentLock
支持重进入的锁,能够支持一个线程对资源的重复加锁,代码见上面。
读写锁 ReetrentReadWriteLock
特性
公平性选择
重进入
锁降级
接口示例
int getReadLockCount()
读锁被或许的次数
int getReadHoldCount()
当前线程或许读锁的次数
int getWriteLockCount()
int getWriteHoldCount()
通过Cache来解释读写锁,HashMap是非线程安全的,通过读写锁实现Cache的线程安全
public class Cache {
static Map map = new HashMap();
static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
static Lock r = rwl.readLock();
static Lock w = rwl.writeLock();
public static final Object get(String key){
r.lock();
try {
return map.get(key);
}finally {
r.unlock();
}
}
public static final Object put(String key,Object value){
w.lock();
try {
return map.put(key,value);
}finally {
w.unlock();
}
}
public static final void clear() {
w.lock();
try {
map.clear();
}finally {
w.unlock();
}
}
}
Condition接口和示例
public class ConditionUseCase {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public static void main(String[] args){
}
public void conditionWait() throws InterruptedException {
lock.lock();
try {
condition.await();
}finally {
lock.unlock();
}
}
public void conditionSignal(){
lock.lock();
try {
condition.signal();
}finally {
lock.unlock();
}
}
}
部分方法描述
void await()
当前线程进入等待状态,直到被通知或中断
void awaitUninterruptibly()
当前线程进入等待状态,对中断不敏感
long awaitNanos(long nanosTimeout)
当前线程进入等待状态,直到被通知,中断或者超时,返回值表示剩余的时间,返回值如果是0或者负数,那么可以认定已经超时了
boolean awaitUntil(Date deadline)
当前线程进入等待状态,直到被通知、中断或者到某个时间,如果没有到指定时间,返回true,否则到了指定时间,返回false
void signal()
唤醒一个等待在condition中的线程,该线程从等待方法返回前必须获取与Condition相关联的锁
void signlAll()
唤醒所有等待的condition中的线程,能够从等待方法返回的线程必须获得与condition相关联的锁
有界队列BoundedQueue解释Condition
public class BoundedQueue {
private Object[] items;
private int addIndex,removeIndex,count;
private Lock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
public BoundedQueue(int size){
items = new Object[size];
}
public void add(T t) throws InterruptedException {
lock.lock();
try {
while(count == items.length)
notFull.await();
items[addIndex] = t;
if(++addIndex == items.length)
addIndex = 0;
++count;
notEmpty.signal();
}finally {
lock.unlock();
}
}
public T remove() throws InterruptedException {
lock.lock();
try {
while(count == 0)
notEmpty.await();
Object x = items[removeIndex];
if(++removeIndex == items.length)
removeIndex = 0;
--count;
notFull.signal();
return (T) x;
}finally {
lock.unlock();
}
}
}