使用Unsafe来实现自定义锁
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来实现自定义锁的更多相关文章
- 【腾讯Bugly干货分享】浅谈Android自定义锁屏页的发车姿势
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57875330c9da73584b025873 一.为什么需要自定义锁屏页 锁屏 ...
- 浅谈 Android 自定义锁屏页的发车姿势
作者:blowUp,原文链接:http://mp.weixin.qq.com/s?__biz=MzA3NTYzODYzMg==&mid=2653577446&idx=2&sn= ...
- 重新想象 Windows 8.1 Store Apps (92) - 其他新特性: CoreDispatcher, 日历, 自定义锁屏系列图片
[源码下载] 重新想象 Windows 8.1 Store Apps (92) - 其他新特性: CoreDispatcher, 日历, 自定义锁屏系列图片 作者:webabcd 介绍重新想象 Win ...
- 浅谈Android自定义锁屏页的发车姿势
一.为什么需要自定义锁屏页 锁屏作为一种黑白屏时代就存在的手机功能,至今仍发挥着巨大作用,特别是触屏时代的到来,锁屏的功用被发挥到了极致.多少人曾经在无聊的时候每隔几分钟划开锁屏再关上,孜孜不倦,其酸 ...
- 模仿ReentrantLock类自定义锁
简介 临近过年了,没什么需求,今天模仿ReentrantLock自定义写了一个自己锁,在这里记录一下,前提是对AQS原理有所了解,分享给大家 1.自定义锁MyLock package com.jack ...
- 自定义锁屏图片 win7
win + R打开运行对话框 输入Regedit 点确定 进入注册表,找到以下项次 HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows/CurrentVersi ...
- 005-多线程-锁-JUC锁-LockSupport【使用、Unsafe、对比Object的wait、底层源码】
一.概述 在Java多线程中,当需要阻塞或者唤醒一个线程时,都会使用LockSupport工具类来完成相应的工作.LockSupport定义了一组公共静态方法,这些方法提供了最基本的线程阻塞和唤醒功能 ...
- c#自定义业务锁
我们有这样的使用场景,某个订单在修改信息的时候,其他人不能修改相关的信息,比如不能做支付,不能退单等等,那么我们可以根据单号进行加锁,多Monitor做了如下扩展 定义接口 //// 文件名称:ILo ...
- 万字长文!从底层开始带你了解并发编程,彻底帮你搞懂java锁!
线程是否要锁住同步资源 锁住 悲观锁 不锁住 乐观锁 锁住同步资源失败 线程是否要阻塞 阻塞 不阻塞自旋锁,适应性自旋锁 多个线程竞争同步资源的流程细节有没有区别 不锁住资源,多个线程只有一个能修改资 ...
随机推荐
- 02.list--约瑟夫环
from fib import fib # 参考01.线性表 def josephus_a(n, k, m): """ 约瑟夫环 没有人用0表示,n个人出列即结束 :pa ...
- RMQ Topic
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11794927.html RMQ Topic Project Directory Maven Depen ...
- hdu 6044 : Limited Permutation (2017 多校第一场 1012) 【输入挂 组合数学】
题目链接 参考博客: http://blog.csdn.net/jinglinxiao/article/details/76165353 http://blog.csdn.net/qq_3175920 ...
- 【leetcode】778. Swim in Rising Water
题目如下: 解题思路:本题题干中提到了一个非常重要的前提:"You can swim infinite distance in zero time",同时也给了一个干扰条件,那就是 ...
- Prometheus + Node Exporter + Grafana 监控主机运行信息
上一篇文章中讲了如何利用Prometheus和Grafana监控SpringBoot应用的JVM信息,这次就来看看如何监控 服务器运行状态,先列出用到的工具: Prometheus node_ex ...
- 关于DNS
一.什么是DNS DNS 是域名系统 (Domain Name System) 的缩写,它是由解析器和域名服务器组成的.域名服务器是指保存有该网络中所有主机的域名和对应IP地址,并具有将域名转换为IP ...
- js执行上下文与执行上下文栈
一.什么是执行上下文 简单说就是代码运行时的执行环境,必须是在函数调用的时候才会产生,如果不调用就不会产生这个执行上下文.在这个环境中,所有变量会被事先提出来(变量提升),有的直接赋值,有的为默认值 ...
- python学习笔记(十一)处理json
json串就是字符串,json串里必须是双引号 d={'car':{'color':'red','price':100,'count':50}, '爱分叉':{'color':'red','price ...
- php中间件是什么
php中间件(middleware)是一个闭包,而且返回一个闭包. 中间件为过滤进入应用的HTTP请求提供了一套便利的机制,可以分为前置中间件和后置中间件.常用于验证用户是否经过认证,添加响应头(跨域 ...
- iOS设计模式之桥接模式
一,什么是桥接模式 定义 抽象出层次结构.上层抽象接口的职能,实现上层抽象接口的职能,层级间的通信协议(可以抽象为接口).桥接模式的目的,就是把抽象层次结构从具体的实现中分离出来,使其能够独立变更.抽 ...