当前位置: 首页 > news >正文

用muse做网站seo网站关键词快速排名

用muse做网站,seo网站关键词快速排名,app软件制作器,体育新闻网站的建设文章目录 一、读写锁介绍二、ReentrantReadWriteLock底层原理1. 读写锁的设计 一、读写锁介绍 现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)。在没有写操作的时候,多个线程同时读一个资源没有任何问题&#xf…

文章目录

    • 一、读写锁介绍
    • 二、ReentrantReadWriteLock底层原理
      • 1. 读写锁的设计

一、读写锁介绍

现实中有这样一种场景:对共享资源有读和写的操作,且写操作没有读操作那么频繁(读多写少)。在没有写操作的时候,多个线程同时读一个资源没有任何问题,所以应该允许多个线程同时读取共享资源(读读可以并发);但是如果一个线程想去写这些共享资源,就不应该允许其他线程对该资源进行读和写操作了(读写,写读,写写互斥)。在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量。

针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它内部,维护了 一对相关的锁,一个用于只读操作,称为读锁;一个用于写入操作,称为写锁。

线程进入读锁的前提条件:

  • 没有其它线程的写锁
  • 没有写请求或者有写请求,但是调用线程和持有锁的线程是同一个

线程进入写锁的前提条件:

  • 没有其他线程的读锁
  • 没有其他线程的写锁

读写锁有以下三个重要的特性:

  • 公平选择性:支持非公平和公平的锁获取方式,吞吐量还是非公平优于公平
  • 可重入:读锁和写锁都支持线程重入,以读写线程为例,读锁获取读锁后,能够再次获取读锁,写线程在获取写锁之后能够再次获取写锁,同时也可以获取读锁。
  • 锁降级:遵循获取写锁,再获取读锁最后释放写锁的次序,写锁能够降级为读锁。

二、ReentrantReadWriteLock底层原理

看源码需要了解三个核心问题

  1. 读写锁是怎样实现分别记录读写状态的?
  2. 写锁时怎么获取和释放的?
  3. 读锁时怎么获取和释放的?

1. 读写锁的设计

在这里插入图片描述
首先看它的类信息:

public class ReentrantReadWriteLockimplements ReadWriteLock, java.io.Serializable {}

可以发现该类实现了ReadWriteLock这个接口

public interface ReadWriteLock {Lock readLock();Lock writeLock();
}

该接口就实现了读锁和写锁的规范,以下就是相关的类图

在这里插入图片描述
下面看看ReentrantReadWriteLock的读写锁的实现逻辑,首先看写锁:

public static class ReadLock implements Lock, java.io.Serializable {private static final long serialVersionUID = -5992448646407690164L;private final Sync sync;protected ReadLock(ReentrantReadWriteLock lock) {sync = lock.sync;}public void lock() {sync.acquireShared(1);}public void lockInterruptibly() throws InterruptedException {sync.acquireSharedInterruptibly(1);}public boolean tryLock() {return sync.tryReadLock();}public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));}public void unlock() {sync.releaseShared(1);}public Condition newCondition() {throw new UnsupportedOperationException();}public String toString() {int r = sync.getReadLockCount();return super.toString() +"[Read locks = " + r + "]";}}
  • ReadLock:是一个ReetrantReadWriteLock的静态内部类
  • Sync:和ReentrantLock一样,Sync也是ReetrantReadWriteLock的一个静态内部抽象类,它继承了AbstractQueuedSynchronizer,实现了AQS的逻辑,然后它会有两种实现,分别是FairSync公平锁,和NonfairSync非公平锁
  • lock:可以发现加读锁加的是AQS的共享锁
  • tryLock:尝试获取读锁

然后看看写锁是怎么实现的

 public static class WriteLock implements Lock, java.io.Serializable {private static final long serialVersionUID = -4992448646407690164L;private final Sync sync;protected WriteLock(ReentrantReadWriteLock lock) {sync = lock.sync;}public void lock() {sync.acquire(1);}public void lockInterruptibly() throws InterruptedException {sync.acquireInterruptibly(1);}public boolean tryLock( ) {return sync.tryWriteLock();}public boolean tryLock(long timeout, TimeUnit unit)throws InterruptedException {return sync.tryAcquireNanos(1, unit.toNanos(timeout));}public void unlock() {sync.release(1);}public Condition newCondition() {return sync.newCondition();}public String toString() {Thread o = sync.getOwner();return super.toString() + ((o == null) ?"[Unlocked]" :"[Locked by thread " + o.getName() + "]");}public boolean isHeldByCurrentThread() {return sync.isHeldExclusively();}public int getHoldCount() {return sync.getWriteHoldCount();}}

下面我们需要思考一个核心问题,读写锁的状态是怎么用AQS底层的state状态来维护的。其实这里的核心问题就是,如何用一个变量维护多种状态。在 ReentrantLock 中,使用 Sync ( 实际是 AQS )的 int 类型的 state 来表示同步状态,表示锁被一个线程重复获取的次数。但是,读写锁 ReentrantReadWriteLock 内部维护着一对读写锁,如果要用一个变量维护多种状态,需要采用“按位切割使用”的方式来维护这个变量,将其切分为两部分:高16为表示读,低16为表示写。分割之后,读写锁是如何迅速确定读锁和写锁的状态呢? 其实底层是通过位运算来实现的。假如当前同步状态为S, 那么写状态,等于 S & 0x0000FFFF(将高 16 位全部抹去)。 当写状态加1,等于S+1。读状态,等于 S >>> 16 (无符号补 0 右移 16 位)。当读状态加1,等于 S+(1<<16),也就是S+0x00010000。根据状态的划分能得出一个推论:S不等于0时,当写状态(S&0x0000FFFF)等于0时,则读状态(S>>>16)大于0,即读锁已被获取。
在这里插入图片描述
源码如下:

//该部分在Sync类中static final int SHARED_SHIFT   = 16;static final int SHARED_UNIT    = (1 << SHARED_SHIFT);static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;/** Returns the number of shared holds represented in count  */static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }/** Returns the number of exclusive holds represented in count  */static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
  • exclusiveCount:获得持有写状态的锁的次数
  • sharedCount:获得持有读状态的锁的线程数量,不同于写锁,读锁利用同时被多个线程持有,而每个线程持有的读锁支持重入的特性,所以需要每个线程持有的读锁数量单独计数,这就需要HoldCounter计数器。

HoldCounter计数器
读锁的内在机制其实就是一个共享锁。一次共享锁的操作就相当于对HoldCounter 计数器的操作。获取共享锁,则该计数器 + 1,释放共享锁,该计数器 - 1。只有当线程获取共享锁后才能对共享锁进行释放、重入操作。

static final class HoldCounter {int count = 0;// Use id, not reference, to avoid garbage retentionfinal long tid = getThreadId(Thread.currentThread());}static final class ThreadLocalHoldCounterextends ThreadLocal<HoldCounter> {public HoldCounter initialValue() {return new HoldCounter();}}

写锁的获取
写锁是一个支持重进入的排它锁。如果当前线程已经获取了写锁,则增加写状态。如果当前线程在获取写锁时,读锁已经被获取(读状态不为0)或者该线程不是已经获取写锁的线程, 则当前线程进入等待状态。

protected final boolean tryAcquire(int acquires) {
//获取当前线程Thread current = Thread.currentThread();//获取当前state的值int c = getState();//获取写锁的重入次数int w = exclusiveCount(c);//state!=0则表示当前有写锁或读锁if (c != 0) {//判断是否是重入if (w == 0 || current != getExclusiveOwnerThread())return false;if (w + exclusiveCount(acquires) > MAX_COUNT)throw new Error("Maximum lock count exceeded");//获取重入锁setState(c + acquires);return true;}// writerShouldBlock有公平与非公平的实现, 非公平返回false,会尝试通过cas加锁,c==0 写锁未被任何线程获取,当前线程是否阻塞或者cas尝试获取锁if (writerShouldBlock() ||!compareAndSetState(c, c + acquires))return false;//设置锁由当前线程独占setExclusiveOwnerThread(current);return true;}

上面简单的代码就实现了下面的逻辑:

  • 读写互斥
  • 写写互斥
  • 写锁支持同一个线程重入
  • writeShouldBlock写锁是否阻塞实现取决公平与非公平的策略
    在这里插入图片描述

写锁的释放

     protected final boolean tryRelease(int releases) {if (!isHeldExclusively())throw new IllegalMonitorStateException();//设置状态int nextc = getState() - releases;boolean free = exclusiveCount(nextc) == 0;//如果state为0,表示释放写锁if (free)setExclusiveOwnerThread(null);setState(nextc);return free;}

在这里插入图片描述
读锁的获取

protected final int tryAcquireShared(int unused) {//获取当前线程Thread current = Thread.currentThread();//获取stateint c = getState();//exclusiveCount(c) != 0 判断是否有写锁//getExclusiveOwnerThread() != current),判断当前线程是否是写锁的持有者if (exclusiveCount(c) != 0 &&getExclusiveOwnerThread() != current)return -1;int r = sharedCount(c);if (!readerShouldBlock() &&r < MAX_COUNT &&//cas加读锁compareAndSetState(c, c + SHARED_UNIT)) {//r==0表示第一次获取读锁if (r == 0) {//设置第一个读为当前线程firstReader = current;//设置当前读锁的重入次数firstReaderHoldCount = 1;} else if (firstReader == current) {          //第一个读的重入firstReaderHoldCount++;} else {//若不是第一个读,则用HoldCounter记录HoldCounter rh = cachedHoldCounter;//第一次读锁获取失败,再次尝试if (rh == null || rh.tid != getThreadId(current))cachedHoldCounter = rh = readHolds.get();else if (rh.count == 0)readHolds.set(rh);rh.count++;}return 1;}return fullTryAcquireShared(current);//第一次读锁获取失败,再次尝试(fullTryAcquireShared)}

上面代码的逻辑就实现了:

  • 读锁共享,读读不互斥
  • 读锁可重入,每个获取读锁的线程都会记录对应的重入数
  • 读写互斥,锁降级场景除外
  • 支持锁降级,持有写锁的线程,可以获取读锁,但是后续要记得把读锁和写锁读释放
  • readerShouldBlock读锁是否阻塞实现取决公平与非公平的策略(FairSync和NonfairSync)

在这里插入图片描述
读锁的释放

protected final boolean tryReleaseShared(int unused) {Thread current = Thread.currentThread();if (firstReader == current) {// assert firstReaderHoldCount > 0;if (firstReaderHoldCount == 1)firstReader = null;elsefirstReaderHoldCount--;} else {HoldCounter rh = cachedHoldCounter;if (rh == null || rh.tid != getThreadId(current))rh = readHolds.get();int count = rh.count;if (count <= 1) {readHolds.remove();if (count <= 0)throw unmatchedUnlockException();}--rh.count;}for (;;) {int c = getState();int nextc = c - SHARED_UNIT;if (compareAndSetState(c, nextc))return nextc == 0;}}

在这里插入图片描述

http://www.mmbaike.com/news/29645.html

相关文章:

  • 网站开发项目流程图模板百度推广要多少钱
  • 精湛的网站设计武汉seo百度
  • 网站开发会用到的框架icp备案查询官网
  • 开封做网站睿艺美百度学术官网入口
  • 世界杯网站建设做网站
  • 采购网站官网seo怎么收费的
  • 凡科做网站怎么样网站内部链接优化方法
  • 广东佛山今日最新通告东莞网络优化公司
  • vs2017 做c 网站自助建站系统
  • 网站备案号怎么看软文推广哪个平台好
  • 怎么判断网站有没有做百度商桥培训报名
  • 北京智联招聘官方网站做家政3322免费域名注册
  • 网站现在一般做多大尺寸北京网站优化托管
  • 专门做qq小工具的网站站长工具之家seo查询
  • 域名跟空间都有了怎么做网站百度最新推广产品
  • 网站项目如何做需求分析在线磁力搜索神器
  • 适合代码新手做的网站无限制搜索引擎排名
  • 企业网站托管注意事项网站推广软件有哪些
  • 怎么用织梦做本地网站公关公司排名
  • 网站常用颜色优化营商环境的意义
  • 婚纱网站策划书seo实战密码第三版
  • 什么网站会更有浏览量开发定制软件公司
  • 做网站最主要是什么河南网站优化公司哪家好
  • 中国开头的网站怎么做营销方案案例
  • 返利导购网站建设需求文档东莞网络推广系统
  • 宁波建设seo优化步骤
  • 张家界工程建设信息网站宁波seo如何做推广平台
  • 合肥专业的房产网站建设seo怎么快速提高排名
  • 网站开发语言有哪些百度快速排名工具
  • 微商招商网站源码打广告的免费软件