1.使用Unsafe类

import sun.misc.Unsafe;

class UnsafePackage {
private static Unsafe unsafe; static {
try {
Class<Unsafe> unsafeClass = Unsafe.class;
Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (Unsafe) theUnsafe.get(null);
} catch (Exception ex) {
ex.printStackTrace();
}
} public static Unsafe getUnsafe() {
return unsafe;
}
}

2.声明简单锁

class CustomLock {
private volatile int status; private static Unsafe unsafe = UnsafePackage.getUnsafe();
private static long statusOffset;
private WaitingQueue queue = new WaitingQueue(); static {
try {
statusOffset = unsafe.objectFieldOffset(CustomLock.class.getDeclaredField("status"));
} catch (Exception ex) {
ex.printStackTrace();
}
} private boolean comareAndSetStatus(int originalStatus, int updateStatus) {
return unsafe.compareAndSwapInt(this, statusOffset, originalStatus, updateStatus);
} public boolean lock() {
if (comareAndSetStatus(0, 1)) {
//System.out.println("竞争锁成功!继续执行后面的代码");
return true;
} //System.out.println("竞争锁失败!进入等待队列");
push(Thread.currentThread());
while (!comareAndSetStatus(0, 1)) {
UnsafePackage.getUnsafe().park(false, 0);
}
return true;
} public boolean unlock() {
status = 0;
Thread thread = pop();
if (thread != null) {
UnsafePackage.getUnsafe().unpark(thread);
}
return true;
} private void push(Thread thread) {
queue.push(thread);
} private Thread pop() {
return queue.pop(); }
}

3.竞争锁失败的进队列

class WaitingQueue {
private volatile int status;
private static long statusOffset; /**
* 非线程安全,使用时,也要加锁
*/
private LinkedList<Thread> queue = new LinkedList<>(); static {
try {
statusOffset = UnsafePackage.getUnsafe().objectFieldOffset(WaitingQueue.class.getDeclaredField("status"));
} catch (Exception ex) {
ex.printStackTrace();
}
} public void push(Thread thread) {
while (!comareAndSetStatus(0, 1)) { }
queue.offerLast(thread);
comareAndSetStatus(1, 0);
return;
} public Thread pop() {
while (!comareAndSetStatus(0, 1)) { }
Thread elem = null;
if (!queue.isEmpty()) {
elem = queue.pop();
}
comareAndSetStatus(1, 0);
return elem;
} private boolean comareAndSetStatus(int originalStatus, int updateStatus) {
return UnsafePackage.getUnsafe().compareAndSwapInt(this, statusOffset, originalStatus, updateStatus);
}
}

3.调用如下

public class CustomLockTest {

    private static int count = 0;

    public static void main(String[] args) throws InterruptedException {
int threadCount = 1500;
CountDownLatch countDownLatch = new CountDownLatch(threadCount);
CustomLock lock = new CustomLock();
long start = System.currentTimeMillis();
IntStream.range(0, threadCount)
.forEach(p -> {
new Thread() {
@Override
public void run() {
lock.lock();
try {
for (int i = 0; i < 1000; i++) {
count++;
}
countDownLatch.countDown();
} finally {
lock.unlock();
}
}
}.start();
}); countDownLatch.await();
long end = System.currentTimeMillis();
System.out.println("结果值为:" + count + ",共花费了" + (end - start) + "毫秒!");
}
}
结果值为:1500000,共花费了601毫秒!

使用Unsafe来实现自定义锁的更多相关文章

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

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

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

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

  3. 重新想象 Windows 8.1 Store Apps (92) - 其他新特性: CoreDispatcher, 日历, 自定义锁屏系列图片

    [源码下载] 重新想象 Windows 8.1 Store Apps (92) - 其他新特性: CoreDispatcher, 日历, 自定义锁屏系列图片 作者:webabcd 介绍重新想象 Win ...

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

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

  5. 模仿ReentrantLock类自定义锁

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

  6. 自定义锁屏图片 win7

    win + R打开运行对话框 输入Regedit 点确定 进入注册表,找到以下项次 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersi ...

  7. 005-多线程-锁-JUC锁-LockSupport【使用、Unsafe、对比Object的wait、底层源码】

    一.概述 在Java多线程中,当需要阻塞或者唤醒一个线程时,都会使用LockSupport工具类来完成相应的工作.LockSupport定义了一组公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能 ...

  8. c#自定义业务锁

    我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多Monitor做了如下扩展 定义接口 //// 文件名称:ILo ...

  9. 万字长文!从底层开始带你了解并发编程,彻底帮你搞懂java锁!

    线程是否要锁住同步资源 锁住 悲观锁 不锁住 乐观锁 锁住同步资源失败 线程是否要阻塞 阻塞 不阻塞自旋锁,适应性自旋锁 多个线程竞争同步资源的流程细节有没有区别 不锁住资源,多个线程只有一个能修改资 ...

随机推荐

  1. 伊朗Cisco路由器遭黑客攻击 全国互联网几乎瘫痪

    2018年4月9日,黑客攻击了伊朗的国家信息数据中心.伊朗internet信息安全部称,此次大规模袭击影响了全球约二十万个思科Cisco路由交换器,也包括伊朗的几千个路由器.攻击也影响了互联网服务供应 ...

  2. C++ begin()和end()

    begin(a)指向数组a的第一个元素,end(a)指向数组a最后一个元素之后的一个元素 #include <iostream> using namespace std; int main ...

  3. VS2017 IDE 说明

  4. 李满春与WebGIS

    李满春 ,男,1964年6月生,博士,教授,博导.现任南京大学科技处处长.地理信息科学系主任(兼).地理信息系统与遥感研究所所长(兼).国际地球系统科学研究所(学科特区)常务副所长(兼).第六届高等学 ...

  5. ppium使用方法说明

    global driver# 元素定位driver.find_element_by_id("id") # id定位driver.find_element_by_name(" ...

  6. P1541乌龟棋

    传送 这题咋做? 当然是爆搜了. 但是蒟蒻不会爆搜(TLE,WA两开花qwq),更不会记忆化搜索,所以我们换个思路. 注意这句话: 这肯定是有用的(洛咕还不会闲圈到给一句毛用都没有的话),那它有什么用 ...

  7. 【经验分享】 解决CentOS7 安装VMTools提示找不到Kernel头文件的方案

    配置一个Linux的开发环境,用VM10+CentOS7(Kernel版本3.10.0-327.10.1.el7),之后发现VMTools功能不全,查证后发现需要卸载重装,于是开始折腾. 按照各种说明 ...

  8. 测开之路六十一:接口测试平台之interface蓝图

    create的js //添加header的函数function add_header() { // 这里是动态拼接html语句,带着样式,拼凑成页面的 "key [] value []&qu ...

  9. MySQL 基准测试

    这是<高性能 MySQL(第三版)>第二章的读书笔记. 基准测试(benchmark)是针对系统的压力测试,用于掌握系统行为或重新系统的某个状态.sysbench 是常用的 MySQL 基 ...

  10. mooc-IDEA 调试代码--012

    mooc-IDEA 调试代码 添加断点快捷键:ctrl+F8 单步运行:F9  <=>resum(从一个断点跳转到下一个断点) 一行一行运行:F8 查看所有断点: 禁止所有断点: 条件断点 ...