4.3.1 Lock接口及其实现

Lock API

Locks包 类层次结构

在这里插入图片描述

Lock 接口方法

在这里插入图片描述

Condition的使用来实现简单的BlockingQuen

线程虚假唤醒:是一个表象,即在多处理器的系统下发出wait的程序有可 能在没有notify唤醒的情形下苏醒继续执行
https://www.zhihu.com/question/50892224

public class BlockingQueue_Demo {


    public static void main(String[] args) throws InterruptedException {
        KaneBlockingQueue kaneBlockingQueue = new KaneBlockingQueue(6);

        new Thread(){
            @Override
            public void run() {
                for (int i = 0; i <20 ; i++) {
                    kaneBlockingQueue.put("x"+i);
                }
            }
        }.start();

        Thread.sleep(1000L);
        System.out.println("开始取元素");
        for (int i = 0; i <10 ; i++) {
            kaneBlockingQueue.take();
            Thread.sleep(2000);

        }
    }




}
class KaneBlockingQueue{

    List<Object> list = new ArrayList<>();
    private Lock lock = new ReentrantLock();
    private Condition putCondition = lock.newCondition(); //condition可以有多个,针对不同的操作放入不同condition,相当于等待队列
    private Condition takeCondition = lock.newCondition();
    private int length;

    public KaneBlockingQueue(int length){
        this.length =length;
    }

    public void  put(Object obj){
        lock.lock(); //思考一个读一个写,为什么要加锁呢?
        try{
            while (true) {//防止线程被虚假唤醒  虚假唤醒(spurious wakeup)是一个表象,即在多处理器的系统下发出wait的程序有可能在没有notify唤醒的情形下苏醒继续执行
                if (list.size() < length) { //我们集合的长度不能超过规定的长度,才能向里面放东西
                    list.add(obj);
                    System.out.println("队列中放入元素:"+obj);
                    takeCondition.signal();
                    return;
                } else { //如果放不进去,就该阻塞. --利用condition实现
                    putCondition.await();//挂起
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public Object take(){
        lock.lock();
        try{
            while (true) {
                if (list.size() > 0) {
                    Object obj = list.remove(0);
                    System.out.println("队列中取得元素:"+obj);
                    putCondition.signal();
                    return obj;
                } else {
                    takeCondition.await();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            return null;
        }
    }
}

ReentrantLock

什么是可重入

可重入是指同一个线程中可以多次去获取锁。
在这里插入图片描述`在这里插入图片描述


class LarZhuReentrantLock implements Lock{
    //重入次数
    AtomicInteger count =new AtomicInteger(0);
    //锁拥有者
    AtomicReference<Thread> owner =new AtomicReference();

    //等待队列
    private LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue();
    @Override
    public void lock() {
        if(!tryLock()){
            //将线程放入到waiting set
            waiters.offer(Thread.currentThread());

            while (true){
                //若线程是队列头部,先判断一次,现在能不能去抢,然后再去加锁
                Thread head = waiters.peek();
                if(head==Thread.currentThread()){
                    if(!tryLock()){
                        // 没有抢到锁继续park
                        LockSupport.park();
                    }else{
                        //签到锁, 将线程出队列
                        waiters.poll();
                        return;
                    }
                }else {
                    //伪唤醒后, 继续park。
                    LockSupport.park();
                }
            }

        }else {
            return;
        }
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        //判断count时否为0 ,
        if(count.intValue()!=0){
            //锁被占用, 判断是否时当前线程
            if (owner.get()== Thread.currentThread()){
                count.set(count.intValue()+1);
                return true;
            }else {
                return false;
            }
        }else{
            if(count.compareAndSet(count.intValue(),count.intValue()+1)){
                owner.set(Thread.currentThread());
                return true;
            }else{
                return false;
            }
        }
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {

        return false;
    }

    @Override
    public void unlock() {
        if(tryUnlock()){
            Thread head = waiters.peek();
            if(head!=null){
                LockSupport.unpark(head);
            }
        }
    }

    public boolean tryUnlock(){
        if(owner.get()!=Thread.currentThread()) {
            throw new IllegalMonitorStateException();
        }else{
            int ct = count.get();
            int nextc = ct-1;
            count.set(nextc);

            if(nextc==0){ //可重入锁被加锁多次,一旦为0 就释放锁,如果不是0,还得继续释放
                owner.compareAndSet(Thread.currentThread(),null);
                return true;
            }else{
                return false;
            }
        }
    }
    @Override
    public Condition newCondition() {
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值