模仿ReentrantLock类自定义锁

Posted 坏~牧羊人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模仿ReentrantLock类自定义锁相关的知识,希望对你有一定的参考价值。

简介

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

1、自定义锁MyLock

package com.jacky;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * Created by jacky on 2018/2/12.
 */
public class MyLock implements Lock{
    private final Sync sync;

    /**
     * 创建公平锁或非公平锁
     * @param fairFlag
     */
    public MyLock(boolean fairFlag){
       sync = fairFlag ? new FairSync() : new NonFairSync();
    }

    /**
     * 默认是公平锁
     */
    public MyLock(){
        sync = new FairSync();
    }

    /**
     * 获取锁
     */
    @Override
    public void lock() {
         sync.acquire(1);
    }

    /**
     * 获取可中断锁
     * @throws InterruptedException
     */
    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    /**
     * 它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,
     * 也就说这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待
     * @return
     */
    @Override
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    /**
     * 获得可超时的锁
     * @param time
     * @param unit
     * @return
     * @throws InterruptedException
     */
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1,unit.toNanos(time));
    }

    /**
     * 释放锁
     */
    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.new ConditionObject();
    }

    abstract static class Sync extends AbstractQueuedSynchronizer {
        /**
         * 判断当前线程是否获得锁
         * @return
         */
        @Override
        protected boolean isHeldExclusively() {
            return Thread.currentThread() ==getExclusiveOwnerThread();
        }

        /**
         * 尝试释放锁
         * @param arg
         * @return
         */
        @Override
        protected boolean tryRelease(int arg) {
            int newState =getState()-arg;
            setState(newState < 0 ? 0:newState);
            if (newState ==0){
                setExclusiveOwnerThread(null);
            }

            return true;
        }

        final boolean nonfairTryAcquire(int arg) {
            Thread thread = Thread.currentThread();
            int state = getState();
            if (state ==0){
                compareAndSetState(0,state+arg);
                //设置独占线程
                setExclusiveOwnerThread(thread);
                return true;
            }
            if (isHeldExclusively()){
                setState(state+arg);
                return true;
            }
            return false;
        }

    }
    static class FairSync extends Sync{
        /**
         * 尝试公平锁获得锁
         * @param arg
         * @return
         */
        @Override
        public boolean tryAcquire(int arg) {
            Thread thread = Thread.currentThread();
            int state = getState();
            if (state ==0){
                //判断队列是否有数据,有数据就返回获取锁失败(公平锁才会这么做)
                if (hasQueuedPredecessors()){
                    return false;
                }
                compareAndSetState(0,state+arg);
                //设置独占线程
                setExclusiveOwnerThread(thread);
                return true;
            }
            if (isHeldExclusively()){
                setState(state+arg);
                 return true;
            }
            return false;
        }

    }

    static class NonFairSync extends Sync{
        @Override
        public boolean tryAcquire(int arg) {
            return  nonfairTryAcquire(arg);
        }
    }
}

2、测试类

package com.jacky;

import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by jacky on 2018/2/12.
 */
public class MyLockDemo {
    private final static MyLock lock = new MyLock(false);
    //private final static ReentrantLock lock = new ReentrantLock(true);
    private static int num = 0;
    public static void main(String[] args) {
        int count = 2000;
        CountDownLatch countDownLatch = new CountDownLatch(count);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    lock.lock();
                Thread thread = Thread.currentThread();
                System.out.println("--start--"+thread.getName());
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                num++;
                System.out.println("--end--");
                countDownLatch.countDown();
                }finally {
                   lock.unlock();
                }

            }
        };
        Thread thread = null;
        for (int i = 0; i < count; i++) {
            thread = new Thread(runnable,"t"+i);
            thread.start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--num--"+num);
    }
}

 

以上是关于模仿ReentrantLock类自定义锁的主要内容,如果未能解决你的问题,请参考以下文章

多线程(十AQS原理-ReentrantLock实现)

ReentrantLock (独占锁、互斥锁)

互斥锁 & 共享锁

源码分析:①ReentrantLock之公平锁和非公平锁

#yyds干货盘点# JUC锁: ReentrantLock详解

ReentrantLock说明