ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用Unsafe来实现自定义锁

2019-05-24 18:41:57  阅读:226  来源: 互联网

标签:return Thread 自定义 实现 Unsafe private int comareAndSetStatus static


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毫秒!

 

标签:return,Thread,自定义,实现,Unsafe,private,int,comareAndSetStatus,static
来源: https://www.cnblogs.com/zhshlimi/p/10919652.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有