AbstractQueuedSynchronizer简单使用
AQS是JUC中很多同步组件的构建基础,简单来讲,它内部实现主要是状态变量state和一个FIFO队列来完成,同步队列的头结点是当前获取到同步状态的结点,获取同步状态state失败的线程,会被构造成一个结点(或共享式或独占式)加入到同步队列尾部(采用自旋CAS来保证此操作的线程安全),随后线程会阻塞;释放时唤醒头结点的后继结点,使其加入对同步状态的争夺中。
AQS为我们定义好了顶层的处理实现逻辑,我们在使用AQS构建符合我们需求的同步组件时,只需重写tryAcquire,tryAcquireShared,tryRelease,tryReleaseShared几个方法,来决定同步状态的释放和获取即可,至于背后复杂的线程排队,线程阻塞/唤醒,如何保证线程安全,都由AQS为我们完成了,这也是非常典型的模板方法的应用。AQS定义好顶级逻辑的骨架,并提取出公用的线程入队列/出队列,阻塞/唤醒等一系列复杂逻辑的实现,将部分简单的可由使用者决定的操作逻辑延迟到子类中去实现。
package com.abstractqueuesynchronizer;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class SelfAbstractQueueSynchronizer {
//继承AbstractQueuedSynchronizer类
private static class Syn extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1L;
//是否拥有锁
protected boolean isHeldExclusively() {
return getState() == 1;
}
//获取锁
public boolean tryAcquire(int acquires) {
if(compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
//释放所
protected boolean tryRelease(int releases) {
if(getState() == 0)
throw new IllegalMonitorStateException();
setExclusiveOwnerThread(null);
setState(0);
return true;
}
}
private final Syn syn = new Syn();
public void lock() {
syn.acquire(1);
}
public boolean tryLock() {
return syn.tryAcquire(1);
}
public void unlock() {
syn.release(1);
}
public boolean isLocked() {
return syn.isHeldExclusively();
}
}
测试
package com.abstractqueuesynchronizer; import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier; public class Main { private static CyclicBarrier barrier = new CyclicBarrier(31);
private static int a = 0;
private static SelfAbstractQueueSynchronizer test = new SelfAbstractQueueSynchronizer(); public static void main(String[] args) throws InterruptedException, BrokenBarrierException { for(int i = 0; i < 30; i++) {
Thread t = new Thread(new Runnable(){ @Override
public void run() {
for(int i = 0; i < 1000; i++) {
unlockIncrement();
}
try {
barrier.await();
} catch (Exception e) {
e.printStackTrace();;
}
} });
t.start();
} barrier.await();
System.out.println("unlock model a= " + a); System.out.println("##########################"); barrier.reset();
a = 0;
for(int i = 0; i < 30; i++) {
Thread t = new Thread(new Runnable(){
@Override
public void run() {
for(int i = 0; i < 1000; i++ ) {
lockIncrement();
} try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
} });
t.start();
} barrier.await();
System.out.println("lock model a= " + a); } public static void unlockIncrement() {
a++;
} public static void lockIncrement() {
test.lock();
a++;
test.unlock();
} }
AbstractQueuedSynchronizer简单使用的更多相关文章
- JUC锁框架_AbstractQueuedSynchronizer详细分析
AQS是JUC锁框架中最重要的类,通过它来实现独占锁和共享锁的.本章是对AbstractQueuedSynchronizer源码的完全解析,分为四个部分介绍: CLH队列即同步队列:储存着所有等待 ...
- AbstractQueuedSynchronizer的简单分析
说明:本作者是文章的原创作者,转载请注明出处:本文地址:http://www.cnblogs.com/qm-article/p/7955781.html 一.AbstractQueuedSynchro ...
- AbstractQueuedSynchronizer的简单介绍
AbstractQueuedSynchronizer简称为AQS.大多数开发者不会直接使用AQS,标准同步器类的集合能够满足绝大多数情况的需求. 1.AbstractQueuedSynchronize ...
- Java并发基础框架AbstractQueuedSynchronizer初探(ReentrantLock的实现分析)
AbstractQueuedSynchronizer是实现Java并发类库的一个基础框架,Java中的各种锁(RenentrantLock, ReentrantReadWriteLock)以及同步工具 ...
- 并发编程 20—— AbstractQueuedSynchronizer 深入分析
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- Java Concurrent之 AbstractQueuedSynchronizer
ReentrantLock/CountDownLatch/Semaphore/FutureTask/ThreadPoolExecutor的源码中都会包含一个静态的内部类Sync,它继承了Abstrac ...
- Java并发包源码学习之AQS框架(四)AbstractQueuedSynchronizer源码分析
经过前面几篇文章的铺垫,今天我们终于要看看AQS的庐山真面目了,建议第一次看AbstractQueuedSynchronizer 类源码的朋友可以先看下我前面几篇文章: <Java并发包源码学习 ...
- 通过ReentrantLock源代码分析AbstractQueuedSynchronizer独占模式
1. 重入锁的概念与作用 reentrant 锁意味着什么呢?简单来说,它有一个与获取锁相关的计数器,如果已占有锁的某个线程再次获取锁,那么lock方法中将计数器就加1后就会立刻返回.当释 ...
- 从一个简单的Java单例示例谈谈并发
一个简单的单例示例 单例模式可能是大家经常接触和使用的一个设计模式,你可能会这么写 public class UnsafeLazyInitiallization { private static Un ...
随机推荐
- 在idea中把springboot项目打成jar包遇到的问题(没有主清单属性)
正确的姿势:<plugin> <groupId>org.springframework.boot</groupId> <artifactId>sprin ...
- 576 C
C. MP3 爆ll == #include<bits/stdc++.h> using namespace std; typedef long long ll; #define P pai ...
- (转)深入详解Java线程池——Executor框架
转:https://yq.aliyun.com/articles/633782?utm_content=m_1000015330 在Java中,使用线程来异步执行任务.Java线程的创建与销毁需要一定 ...
- MySql常用语句总结更新
1.Mysql修改字段的默认值: alter table tablename alter column drop default; (若本身存在默认值,则先删除) alter table tablen ...
- python读写excle
我们可以通过python的一些模块进行excle中用例的读取,或者导出数据到excle 目录 1.安装模块 2.读excle 3.写excle 1.安装模块 python中有第三方模块可以进行excl ...
- MySQL 对比数据库的表结构
有时候,需要对比一下测试环境和生产环境中,数据库的表结构是否有所差异.有两个常用的工具. AmpNmp.DatabaseCompare GUI 界面,支持多种数据库(MySQL.SQL Server. ...
- nacos 报错is not in serverlist
描述 nacos 没有在节点列表里面 查看日志 cd /opt/nacos/ tailf /logs/naming-raft.log <!--报错--> 2019-08-16 17:48: ...
- Python-位操作 ( &,|,~,^,<<,>>
用于提高运算速度,规避算术运算符 在位操作运算中,不应该试图考虑先得到一个数的二进制码 ,而是应该将这个数看作是一个二进制码,二进制补码与整数之间是一一对应的. 诚然Python中有内置函数bin将一 ...
- Python笔记(十五)_异常处理
try-except语句 try: 被检测代码 except Exception [as reason]: 出现异常后的处理代码 例: try: sum = 1+' f=open('未定义文件.txt ...
- Marriage Match II 【HDU - 3081】【并查集+二分答案+最大流】
题目链接 一开始是想不断的把边插进去,然后再去考虑我们每次都加进去边权为1的边,直到跑到第几次就没法继续跑下去的这样的思路,果不其然的T了. 然后,就是想办法咯,就想到了二分答案. 首先,我们一开始处 ...