AQS

目录

一、CLH同步队列

二、手动模拟AQS锁

三、可重入锁ReentrantLock

四、ReentrantLock 和 synchronize异同


一、CLH同步队列

参考:https://blog.csdn.net/weixin_40391011/article/details/104701988

二、手动模拟AQS锁

state可以理解为信号量

public class MyLock implements Lock {

    private Helper helper=new Helper();

    private class Helper extends AbstractQueuedSynchronizer{
        //获取锁
        @Override
        protected boolean tryAcquire(int arg) {
            int state=getState();
            if(state==0){
                //利用CAS原理修改state
                if(compareAndSetState(0,arg)){
                    //设置当前线程占有资源
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
            //else if解决可重入性问题
            }else if(getExclusiveOwnerThread()==Thread.currentThread()){
                setState(getState()+arg);
                return true;
            }
            return false;
        }

        //释放锁
        @Override
        protected boolean tryRelease(int arg) {
            int state=getState()-arg;
            boolean flag=false;
            //判断释放后是否为0
            if(state==0){
                setExclusiveOwnerThread(null);
                setState(state);
                return true;
            }
            setState(state);//存在线程安全吗?重入性的问题,当前已经独占了资源()state
            return false;
        }

        public Condition newConditionObjecct(){
            return new ConditionObject();
        }
    }
    @Override
    public void lock() {
        helper.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        helper.acquireInterruptibly(1);
    }

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

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return helper.tryAcquireNanos(1,unit.toNanos(time));
    }

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

    @Override
    public Condition newCondition() {
        return helper.newConditionObjecct();
    }
}

三、可重入锁ReentrantLock

同一个锁对同一资源进行占有的时候,直接分配给这个线程

ReentrantLock是独占式可重入锁,默认是非公平锁,可以具体设置为公平锁还是非公平锁。

实例:

import java.util.concurrent.locks.ReentrantLock;

public class Demo03 {
    private ReentrantLock lock=new ReentrantLock();
    private int m=0;
    public void a(){
        lock.lock();
        System.out.println("a");
        b();
        lock.unlock();
    }
    public void b(){
        lock.lock();
        System.out.println("b");
        lock.unlock();
    }

    public static void main(String[] args) {
        Demo03 demo=new Demo03();
        new Thread(()->{
            demo.a();
        }).start();
    }
}

注意点:

       锁降级:由写锁到读锁。在释放写锁(write.unlock)之前需要加上读锁(read.lock())

锁升级:由读锁到写锁。但是在ReentrantReadWriteLock中不支持。

ReentrantReadWriteLock:锁是一个读写分离的锁,这种锁主要用于读多写少的业务场景,口诀就是:读读共享、写写互斥、读写互斥。

四、ReentrantLock 和 synchronize异同

synchronize 和Lock:

1、synchronize 系java 内置关键字;而Lock 是一个类  

2、synchronize 可以作用于变量、方法、代码块;而Lock 是显式地指定开始和结束位置

3、synchronize 不需要手动解锁,当线程抛出异常的时候,会自动释放锁;而Lock则需要手动释放,所以lock.unlock()需要放在finally 中去执行

4、性能方面,如果竞争不激烈的时候,synchronize 和Lock 的性能差不多,如果竞争激烈的时候,Lock 的效率会比synchronize 高

5、Lock 可以知道是否已经获得锁,synchronize 不能知道。Lock 扩展了一些其他功能如让等待的锁中断、知道是否获得锁等功能;Lock 可以提高效率。

6、synchronize 是悲观锁的实现,而Lock 则是乐观锁的实现,采用的CAS 的尝试机制

 

synchronize 和 ReentrantLock:

ReentrantLock的作用和synchronize是一样的,都是实现锁的功能,但是ReentrantLock需要手写代码对锁进行获取和释放(一定要在finally里面释放),要不然就永远死锁了,ReentrantLock也可以用来做线程之间的挂起和通知,synchronize一般是使用object的wait和notify来实现,ReentrantLock使用Condition来实现线程之间的通信。

除开上面和Lock 的区别,还有一下的一些区别:

1、ReenTrantLock 可以中断锁的等待,提供了一些高级功能;

2、多个线程在等待的时候,可以提供公平的锁;默认的是非公平锁,性能会比公平锁好一些;

3、ReenTrantLock 可以绑定多个锁条件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值