使用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锁!
线程是否要锁住同步资源 锁住 悲观锁 不锁住 乐观锁 锁住同步资源失败 线程是否要阻塞 阻塞 不阻塞自旋锁,适应性自旋锁 多个线程竞争同步资源的流程细节有没有区别 不锁住资源,多个线程只有一个能修改资 ...
随机推荐
- bzoj1875 [SDOI2009]HH去散步 矩阵快速幂
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1875 题解 如果没有这个"不能立刻沿着刚刚走来的路走回",那么这个题就是一 ...
- mac上如何搜索文件?
在Mac上如果你用会了搜索功能那绝对是个事半功倍的技巧.因为Mac本身有强大的文件索引能力, 可以帮你快速的找到你需要的文件.就好比我要找到上周修改过的word文档应该怎么办? * 使用语音命令让Si ...
- vuex的mapState方法来获取vuex的state对象中属性
有两种写法 1.首先在组件中引入vuex的mapState方法: 首先在组件中引入vuex的mapState方法: import { mapState } from 'vuex' 然后在compute ...
- 028:with标签使用详解
with标签使用详解: 1.在模板中享用使用变量,可以通过 with 语句实现: 2.with 有两种用法,具体情况如下 ( 包括注意事项 ) : index.html: <p>wi ...
- Callable使用示例
之前工作中也有使用过Callable,但是却没有使用Thread对象去操作过,今晚 小组培训,涨知识了,现特意记录一下,以免忘记. 先看一下Thread的构造器 可以看到,Thread类并没有提供参数 ...
- BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度
Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...
- [CSP-S模拟测试]:sum(数学+莫队)
题目传送门(内部题63) 输入格式 第一行有一个整数$id$,表示测试点编号.第一行有一个整数$q$,表示询问组数.然后有$q$行,每行有两个整数$n_i,m_i$. 输出格式 一共有$q$行,每行一 ...
- [CSP-S模拟测试]:天才绅士少女助手克里斯蒂娜(数学+树状数组)
题目描述 红莉栖想要弄清楚楼下天王寺大叔的显像管电视对“电话微波炉(暂定)”的影响. 选取显像管的任意一个平面,一开始平面内有个$n$电子,初始速度分别为$v_i$,定义飘升系数为$$\sum \li ...
- Windows 下开启FTP服务并创建FTP用户
Windows 下开启FTP服务,并创建用户 此教程教你怎么开启 Windows 的 FTP 服务,并创建用于登入 FTP 的用户.教程用到的操作系统是 Windows 7. 一.创建用于登入 FTP ...
- Flask框架视图多层装饰器问题
Flask中的app.route装饰器 我们知道,在flask框架中,我们的路由匹配就是通过有参装饰器来实现的,我们看一个简单的例子: from flask import Flask, render_ ...