简介

临近过年了,没什么需求,今天模仿ReentrantLock自定义写了一个自己锁,在这里记录一下,前提是对AQS原理有所了解,分享给大家

1、自定义锁MyLock

package com.jacky;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock; /**
* Created by jacky on 2018/2/12.
*/
public class MyLock implements Lock{
private final Sync sync; /**
* 创建公平锁或非公平锁
* @param fairFlag
*/
public MyLock(boolean fairFlag){
sync = fairFlag ? new FairSync() : new NonFairSync();
} /**
* 默认是公平锁
*/
public MyLock(){
sync = new FairSync();
} /**
* 获取锁
*/
@Override
public void lock() {
sync.acquire(1);
} /**
* 获取可中断锁
* @throws InterruptedException
*/
@Override
public void lockInterruptibly() throws InterruptedException {
sync.acquireInterruptibly(1);
} /**
* 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,
* 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待
* @return
*/
@Override
public boolean tryLock() {
return sync.nonfairTryAcquire(1);
} /**
* 获得可超时的锁
* @param time
* @param unit
* @return
* @throws InterruptedException
*/
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1,unit.toNanos(time));
} /**
* 释放锁
*/
@Override
public void unlock() {
sync.release(1);
} @Override
public Condition newCondition() {
return sync.new ConditionObject();
} abstract static class Sync extends AbstractQueuedSynchronizer {
/**
* 判断当前线程是否获得锁
* @return
*/
@Override
protected boolean isHeldExclusively() {
return Thread.currentThread() ==getExclusiveOwnerThread();
} /**
* 尝试释放锁
* @param arg
* @return
*/
@Override
protected boolean tryRelease(int arg) {
int newState =getState()-arg;
setState(newState < 0 ? 0:newState);
if (newState ==0){
setExclusiveOwnerThread(null);
} return true;
} final boolean nonfairTryAcquire(int arg) {
Thread thread = Thread.currentThread();
int state = getState();
if (state ==0){
compareAndSetState(0,state+arg);
//设置独占线程
setExclusiveOwnerThread(thread);
return true;
}
if (isHeldExclusively()){
setState(state+arg);
return true;
}
return false;
} }
static class FairSync extends Sync{
/**
* 尝试公平锁获得锁
* @param arg
* @return
*/
@Override
public boolean tryAcquire(int arg) {
Thread thread = Thread.currentThread();
int state = getState();
if (state ==0){
//判断队列是否有数据,有数据就返回获取锁失败(公平锁才会这么做)
if (hasQueuedPredecessors()){
return false;
}
compareAndSetState(0,state+arg);
//设置独占线程
setExclusiveOwnerThread(thread);
return true;
}
if (isHeldExclusively()){
setState(state+arg);
return true;
}
return false;
} } static class NonFairSync extends Sync{
@Override
public boolean tryAcquire(int arg) {
return nonfairTryAcquire(arg);
}
}
}

2、测试类

package com.jacky;

import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock; /**
* Created by jacky on 2018/2/12.
*/
public class MyLockDemo {
private final static MyLock lock = new MyLock(false);
//private final static ReentrantLock lock = new ReentrantLock(true);
private static int num = 0;
public static void main(String[] args) {
int count = 2000;
CountDownLatch countDownLatch = new CountDownLatch(count);
Runnable runnable = new Runnable() {
@Override
public void run() {
try {
lock.lock();
Thread thread = Thread.currentThread();
System.out.println("--start--"+thread.getName());
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
num++;
System.out.println("--end--");
countDownLatch.countDown();
}finally {
lock.unlock();
} }
};
Thread thread = null;
for (int i = 0; i < count; i++) {
thread = new Thread(runnable,"t"+i);
thread.start();
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("--num--"+num);
}
}

模仿ReentrantLock类自定义锁的更多相关文章

  1. 模仿CountDownLatch类自定义倒时计时器

    简介 这里模仿CountDownLatch类自定义到时计时器,利用AQS模板中的尝试获得共享和释放共享 1.MyCountDownLatch package com.jacky; import com ...

  2. 深入理解独占锁ReentrantLock类锁

    ReentrantLock介绍 [1]ReentrantLock是一种基于AQS框架的应用实现,是JDK中的一种线程并发访问的同步手段,它的功能类似于synchronized是一种互斥锁,可以保证线程 ...

  3. 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...

  4. 浅谈 Android 自定义锁屏页的发车姿势

    作者:blowUp,原文链接:http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653577446&idx=2&sn= ...

  5. ReentrantLock类的基本结构

    ReentrantLock类是一个可重入互斥锁,它具有与使用synchronized()方法和语句访问隐式监视器锁相同的基本行为和语义,但是它的功能更强大.ReentrantLock由最近成功获得锁但 ...

  6. 浅谈Android自定义锁屏页的发车姿势

    一.为什么需要自定义锁屏页 锁屏作为一种黑白屏时代就存在的手机功能,至今仍发挥着巨大作用,特别是触屏时代的到来,锁屏的功用被发挥到了极致.多少人曾经在无聊的时候每隔几分钟划开锁屏再关上,孜孜不倦,其酸 ...

  7. 【试验局】ReentrantLock中非公平锁与公平锁的性能测试

    硬件环境: CPU:AMD Phenom(tm) II X4 955 Processor Memory:8G SSD(128G):/ HDD(1T):/home/ 软件环境: OS:Ubuntu14. ...

  8. [图解Java]ReentrantLock重入锁

    图解ReentrantLock 0. demo 我先给出一个demo, 这样大家就可以根据我给的这段代码, 边调试边看源码了. 还是那句话: 注意"My" , 我把Reentran ...

  9. java中的 java.util.concurrent.locks.ReentrantLock类中的lockInterruptibly()方法介绍

    在java的 java.util.concurrent.locks包中,ReentrantLock类实现了lock接口,lock接口用于加锁和解锁限制,加锁后必须释放锁,其他的线程才能进入到里面执行, ...

随机推荐

  1. Spring框架学习08——自动代理方式实现AOP

    在传统的基于代理类的AOP实现中,每个代理都是通过ProxyFactoryBean织入切面代理,在实际开发中,非常多的Bean每个都配置ProxyFactoryBean开发维护量巨大.解决方案:自动创 ...

  2. 【Java并发核心七】计划任务ScheduleExecutorService

    Java中定时任务Timer工具类提供了计划任务的实现,但是Timer工具类是以队列的方式来管理线程的,并不是以线程池的方式,这样在高并发的情况下,运行效率会有点低. ScheduleExecutor ...

  3. 【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 && 场景案例

    上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画 ...

  4. HDU.3032.Nim or not Nim?(博弈论 Lasker's Nim)

    题目链接 \(Description\) 有多堆石子, 每次可以将任意一堆拿走任意个或者将这一堆分成非空的两堆, 拿走最后一颗石子的人胜利.问谁会获得胜利. \(Solution\) Lasker's ...

  5. php中对Mysql数据库的访问操作

    一:  PHP-MySQL 是 PHP 操作 MySQL 资料库最原始的 Extension ,PHP-MySQLi 的 i 代表 Improvement ,提更了相对进阶的功能,就 Extensio ...

  6. 将文件打包成apk

    Android Studio的打包成apk文件 https://blog.csdn.net/woaichimahua/article/details/54427528

  7. git 快照及分支

    分支介绍 分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN. 如果两个平行宇宙互不干扰,那对现在的你也没啥影响.不过,在某个时间点,两个平 ...

  8. javascript中的LHS与RHS

    最近在学习javascript过程中,接触了LHS与RHS的概念,刚开始的时候有点理解不清,现在做一些梳理,方便以后进行理解. LHS与RHS:javascript引擎的两种查找类型,含义是赋值操作的 ...

  9. 查看 Mac/Linux 某端口占用情况

    Mac/Linux 平台下,通用命令: lsof -i:8080  (8080 为 端口号,根据需要,替换为其他端口号) 可以查看该端口被什么程序占用,并显示 pid,方便 kill 掉 Linux如 ...

  10. ASP.NET Web API中把分页信息放Header中返回给前端

    谈到ASP.NET Web API的分页,考虑的因素包括: 1.上一页和下一页的uri2.总数和总页数3.当前页和页容量 接着是服务端的数据以怎样的形式返回? 我们通常这样写: {    totalC ...