自己实现Lock(独享锁)

在线程的通信中,可以通过线程的park和unpark对线程提供许可证,或者将线程禁用。利用此机制,我们可以自己实现锁

  • 首先需要实现lock接口
  •  主要需要实现的接口有lock() unlock() tryLock()等
  • 需要定义一个是否被锁住的原子标识
private final AtomicBoolean locked = new AtomicBoolean();
  • 定义一个等待队列
private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();
  • 在实现lock接口时候,需要考虑伪唤醒问题,所以采用while方式

具体代码如下:

/**
 * 自己实现独享锁
 */
class MillaLock implements Lock {

    //定义是否被锁住的原子标识
    private final AtomicBoolean locked = new AtomicBoolean();
    //定义一个等待队列
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    @Override
    public void lock() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);
        //尝试加锁 在队列中不是第一个或无法获取锁时阻塞
        while (waiters.peek() != current || !tryLock()) {
            //挂起当前线程,没有获取到锁,不继续执行
            LockSupport.park();
            //忽略已经被中断的线程
            if (Thread.interrupted()) {
                wasInterrupted = true;
            }
        }
        waiters.remove();//从队列中移除线程
        //退出时重申中断状态
        if (wasInterrupted) {
            current.interrupt();
        }
    }

    @Override
    public boolean tryLock() {
        //原子操作
        return locked.compareAndSet(false, true);
    }

    @Override
    public void unlock() {
        //释放锁
        locked.set(false);
        //唤醒队列中第一个线程
        LockSupport.unpark(waiters.peek());
    }

    @Override
    public Condition newCondition() {
        return null;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

 测试代码如下

/**
 * @Package: com.milla.study.netbase.expert.concurrent.lock
 * @Description: <自己实现lock>
 * @Author: MILLA
 * @CreateDate: 2020/6/2 16:33
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/6/2 16:33
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public class MillaLockTests {
    private static int count;

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 300; i++) {
            new Thread(() -> add(), i + "").start();
        }
        Thread.sleep(500L);
        System.out.println(count);
    }

    private static final Lock lock = new MillaLock();

    private static void add() {
        lock.lock();
        for (int i = 0; i < 1000; i++) {
            count++;
        }
        lock.unlock();
    }
}

 在LockSupport代码中,有相关锁操作的案例,可作为借鉴,代码如下:

class FIFOMutex {
    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<Thread>();

    public void lock() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);

        // Block while not first in queue or cannot acquire lock
        while (waiters.peek() != current ||
                !locked.compareAndSet(false, true)) {
            LockSupport.park(this);
            if (Thread.interrupted()) // ignore interrupts while waiting
                wasInterrupted = true;
        }

        waiters.remove();
        if (wasInterrupted)          // reassert interrupt status on exit
            current.interrupt();
    }

    public void unlock() {
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }
}

也可以封装程AQS模式

package com.milla.study.netbase.expert.concurrent.lock;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

/**
 * @Package: com.milla.study.netbase.expert.concurrent.lock
 * @Description: <自己实现lock>
 * @Author: MILLA
 * @CreateDate: 2020/6/2 16:33
 * @UpdateUser: MILLA
 * @UpdateDate: 2020/6/2 16:33
 * @UpdateRemark: <>
 * @Version: 1.0
 */
public class MillaLockAQSTests {
    private static int count;

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < 300; i++) {
            new Thread(() -> add(), i + "").start();
        }
        Thread.sleep(500L);
        System.out.println(count);
    }

    private static final Lock lock = new MillaLock();

    private static void add() {
        lock.lock();
        for (int i = 0; i < 1000; i++) {
            count++;
        }
        lock.unlock();
    }
}

/**
 * 自己实现独享锁
 */
class MillaLockAQS implements Lock {
    MillaAQS aqs = new MillaAQS() {

        @Override
        public boolean tryAcquire() {
            return locked.compareAndSet(false, true);
        }

        @Override
        public boolean tryRelease() {
            return locked.compareAndSet(false, false);
        }
    };

    @Override
    public void lock() {
        aqs.acquire();
    }

    @Override
    public boolean tryLock() {
        return aqs.tryAcquire();
    }

    @Override
    public void unlock() {
        aqs.release();
    }

    @Override
    public Condition newCondition() {
        return null;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }
}

class MillaAQS {
    //定义是否被锁住的原子标识
    public final AtomicBoolean locked = new AtomicBoolean();
    //定义一个等待队列
    private final Queue<Thread> waiters = new ConcurrentLinkedQueue<>();

    public void acquire() {
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);
        //尝试加锁 在队列中不是第一个或无法获取锁时阻塞
        while (waiters.peek() != current || !tryAcquire()) {
            //挂起当前线程,没有获取到锁,不继续执行
            LockSupport.park();
            //忽略已经被中断的线程
            if (Thread.interrupted()) {
                wasInterrupted = true;
            }
        }
        waiters.remove();//从队列中移除线程
        //退出时重申中断状态
        if (wasInterrupted) {
            current.interrupt();
        }
    }

    public boolean tryAcquire() {
        throw new UnsupportedOperationException();

    }

    public boolean tryRelease() {
        throw new UnsupportedOperationException();
    }

    public void release() {
        if (tryRelease()) {
            //唤醒队列中第一个线程
            LockSupport.unpark(waiters.peek());
        }
    }


}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值