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. bzoj1875 [SDOI2009]HH去散步 矩阵快速幂

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1875 题解 如果没有这个"不能立刻沿着刚刚走来的路走回",那么这个题就是一 ...

  2. mac上如何搜索文件?

    在Mac上如果你用会了搜索功能那绝对是个事半功倍的技巧.因为Mac本身有强大的文件索引能力, 可以帮你快速的找到你需要的文件.就好比我要找到上周修改过的word文档应该怎么办? * 使用语音命令让Si ...

  3. vuex的mapState方法来获取vuex的state对象中属性

    有两种写法 1.首先在组件中引入vuex的mapState方法: 首先在组件中引入vuex的mapState方法: import { mapState } from 'vuex' 然后在compute ...

  4. 028:with标签使用详解

    with标签使用详解: 1.在模板中享用使用变量,可以通过  with  语句实现: 2.with  有两种用法,具体情况如下 ( 包括注意事项 ) : index.html: <p>wi ...

  5. Callable使用示例

    之前工作中也有使用过Callable,但是却没有使用Thread对象去操作过,今晚 小组培训,涨知识了,现特意记录一下,以免忘记. 先看一下Thread的构造器 可以看到,Thread类并没有提供参数 ...

  6. BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度

    Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...

  7. [CSP-S模拟测试]:sum(数学+莫队)

    题目传送门(内部题63) 输入格式 第一行有一个整数$id$,表示测试点编号.第一行有一个整数$q$,表示询问组数.然后有$q$行,每行有两个整数$n_i,m_i$. 输出格式 一共有$q$行,每行一 ...

  8. [CSP-S模拟测试]:天才绅士少女助手克里斯蒂娜(数学+树状数组)

    题目描述 红莉栖想要弄清楚楼下天王寺大叔的显像管电视对“电话微波炉(暂定)”的影响. 选取显像管的任意一个平面,一开始平面内有个$n$电子,初始速度分别为$v_i$,定义飘升系数为$$\sum \li ...

  9. Windows 下开启FTP服务并创建FTP用户

    Windows 下开启FTP服务,并创建用户 此教程教你怎么开启 Windows 的 FTP 服务,并创建用于登入 FTP 的用户.教程用到的操作系统是 Windows 7. 一.创建用于登入 FTP ...

  10. Flask框架视图多层装饰器问题

    Flask中的app.route装饰器 我们知道,在flask框架中,我们的路由匹配就是通过有参装饰器来实现的,我们看一个简单的例子: from flask import Flask, render_ ...