JAVA JUC 之读写锁的实现(一)

5 篇文章 0 订阅
4 篇文章 0 订阅

基于java JUC(java.util.concurrent)包的读写锁的实现

定义一个线程对象

package readwritelock;

/**
 * @author tongke
 * @email tongkp@126.com
 * @create 2020-07-26 10:25
 */
public class WaitNode {
    int type = 0;   //0 为想获取独占锁的线程, 1为想获取共享锁的线程
    Thread thread = null;
    int arg = 0;

    public WaitNode(Thread thread, int type, int arg) {
        this.type = type;
        this.thread = thread;
        this.arg = arg;
    }
}

读写锁的具体实现类

package readwritelock;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

/**
 * @author tongke
 * @email tongkp@126.com
 * @create 2020-07-26 10:15
 */
public class AppinReadWriteLock {
    volatile AtomicInteger readCount = new AtomicInteger(0);
    AtomicInteger writeCount = new AtomicInteger(0);

    AtomicReference<Thread> owner = new AtomicReference<Thread>();

    //等待队列
    public volatile LinkedBlockingQueue<WaitNode> waiters = new LinkedBlockingQueue<WaitNode>();

    /**
     * 获取独占锁
     */
    public void lock(){
        int arg = 1;
        //尝试获取独占锁,若成功,退出方法,若失败挂起线程
        if(!tryLock(arg)){
            //标记为独占锁
            WaitNode waitNode = new WaitNode(Thread.currentThread(), 0, arg);
            waiters.offer(waitNode);    //进入等待队列
            for (; ;) {
                WaitNode head = waiters.peek();
                if(head != null && head.thread == Thread.currentThread()){
                    if (!tryLock(arg)){     //再次尝试获取独占锁
                        LockSupport.park();     //若失败,挂起线程
                    }else {     //若成功获取 将当前线程从队列头部移除
                        waiters.poll();
                        return;
                    }
                }else {     //若不是队列头部元素
                    LockSupport.park();     //将当前线程挂起
                }
            }
        }
    }

    /**
     * 释放独占锁
     * @return
     */
    public  boolean unlock(){
        int arg = 1;
        //尝试释放独占锁,若成功返回true,若失败返回false
        if(tryUnlock(arg)){
            WaitNode next = waiters.peek(); //取出队列头部的元素
            if (next != null){
                Thread th = next.thread;
                LockSupport.unpark(th);     //唤醒队列头部的线程
            }
            return true;    //成功返回true
        }
        return false;
    }

    /**
     * 尝试获取独占锁
     * @param acquires
     * @return
     */
    public boolean tryLock(int acquires){
        //如果read cout != 0 返回 false
        if(readCount.get() != 0){
            return false;
        }
        int wct = writeCount.get();     //拿到独占锁, 当前状态
        if(wct == 0){   //当前的独占锁未被占用
            if (writeCount.compareAndSet(wct, wct + acquires)){     //通过修改state来抢锁
                owner.set(Thread.currentThread());      //抢到锁后,直接修改owner为当前线程
                return true;
            }
        }else if (owner.get() == Thread.currentThread()){      //当前拿到的独占锁已被占用,判断是否被自己所占用
            writeCount.set(wct+ acquires);  //是被自己占用,则修改count值
            return true;
        }
        return false;
    }

    /**
     * 尝试释放独占锁
     * @param releases
     * @return
     */
    public boolean tryUnlock(int releases){
        //若当前线程没有 持有独占锁
        if (owner.get() != Thread.currentThread()){
            throw new IllegalMonitorStateException();   //抛出异常
        }
        int wc = writeCount.get();
        int nextc = wc - releases;      //计算独占锁剩余占用
        writeCount.set(nextc);      //不管是否完全释放,都更新count值
        if(nextc == 0){     //是否完全释放
            owner.compareAndSet(Thread.currentThread(), null);
            return true;
        }
        return false;
    }

    /**
     * 获取共享锁
     */
    public void lockShared(){
        int arg = 1;
        if(tryLockShared(arg) < 0){   //如果tryAcquireShare失败
            //将当前进程放入队列
            WaitNode node = new WaitNode(Thread.currentThread(), 1, arg);
            waiters.offer(node);    //加入队列
            for (; ; ) {
                //若队列头部的元素是当前线程
                WaitNode head = waiters.peek();
                if(head != null && head.thread == Thread.currentThread()){
                    if(tryLockShared(arg) >= 0){    //尝试获取共享锁,若成功
                        waiters.poll();     // 将当前线程从队列中移除
                        WaitNode next = waiters.peek();
                        if(next != null && next.type == 1){     //如果下一个线程也是等待共享锁
                            LockSupport.unpark(next.thread);    //将其唤醒
                        }
                        return;     //退出方法
                    }else {     //若尝试失败
                        LockSupport.park();     //挂起线程
                    }
                }else {     //若不是头部元素
                    LockSupport.park();     //挂起线程
                }
            }
        }
    }

    /**
     * 释放共享锁
     * @return
     */
    public boolean unLockShared(){
        int arg = 1;
        if(tryUnLockShared(arg)){    //当read count变为0,才叫release share成功
            WaitNode next = waiters.peek();
            if(next != null){
                LockSupport.unpark(next.thread);
            }
            return true;
        }
        return false;
    }

    /**
     * 尝试获取共享锁
     * @param acquires
     * @return
     */
    public int tryLockShared(int acquires){
        for (; ;) {
            if(writeCount.get() != 0 && owner.get() != Thread.currentThread()){
                return -1;
            }
            int rct = readCount.get();
            if (readCount.compareAndSet(rct, rct + acquires)){
                return 1;
            }
        }
    }

    /**
     * 尝试释放共享锁
     * @param releases
     * @return
     */
    public boolean tryUnLockShared(int releases){
        for (;;){
            int rc = readCount.get();
            int nextc = rc - releases;
            if (readCount.compareAndSet(rc, nextc)){
                return nextc == 0;
            }
        }
    }
}

测试类

package readwritelock;

import java.util.ArrayList;
import java.util.List;

/**
 * @author tongke
 * @email tongkp@126.com
 * @create 2020-07-26 18:43
 */
public class TestReadWriteLock {
    static AppinReadWriteLock rwLock = new AppinReadWriteLock();

    static volatile int i = 0;

    static List<String> list = new ArrayList<String>();
    static void add(){
        i++;
    }

    public static void main(String[] args) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        for (int j = 1; j < 20000; j++) {
            final int n = j;
            new Thread(new Runnable() {
                public void run() {
                    if(n % 5 == 0){
                        rwLock.lock();
                        add();
                        rwLock.unlock();
                    }else {
                        rwLock.lockShared();
//                        System.out.println("i=" +i);
                        list.add("i="+i);
                        rwLock.unLockShared();
                    }
                }
            }).start();
        }
        int len = list.size();
        System.out.println("目前耗时:"+ (System.currentTimeMillis() - startTime) / 1000 + "s");
        System.out.println("生产对象:"+ len);
    }
}

代码实现思路来自网易云课堂。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值