java 实现队列读写锁_读书笔记之《Java并发编程的艺术》-java中的锁

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。

欢迎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();

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值