并发编程2 AQS

一、AQS相关面试

1、synchronized 与Rentrantlock 的区别是什么?

Synchronizedjava关键字,可以自动去操作加锁和释放锁,不需要手动编码实现。它的底层行为是由jvm实现的。

 Rentrantlock需要调用加锁和解锁的方法,它的底层是AQS实现的。

区别

Synchronized

Rentrantlock

实现方式

JVM

AQS

是否自动

Yes

no

获取锁

只要资源被锁,会一直等待

针对资源被锁,具有多种处理方式

释放锁

代码执行完毕或者发生异常

手动释放

锁的状态

不能判断

通过 isLocked()

锁的类型

可重入,不可中断

可重入,可中断

锁的公平

非公平锁

非公平锁和非公平锁

 

2、ReentrantLock的加锁方式有几种?分别是什么?

Lock() 如果锁不可用(没抢到),出入线程调度的目的,当前线程将会被禁用到。处于休眠状态,直到获取锁

Boolean tryLock()

如果获取了锁,那么返回true,如果没有获取锁,返回false

Boolean tryLock(long timeout,TimeUnit unit)

如果获得到锁了,那么返回true。如果没有获得锁,处于线程调用的目的,当前线程将会被禁用到,处于休眠状态,直到发生以下情况:

1)已经获得了锁,之前的锁已经被释放了

2)其它一些线程中断了当前线程

3)时间到了

Void lockInterruptibly()

如果获得到锁了,那么返回true。如果没有获取到锁,出入线程调度的目的,当前的线程将会被禁用到,处于休眠状态,直到发生下面几种情况:
 1> 已经获得了锁,之前的锁已经被释放了。
 2> 其他一些线程中断了当前的线程,它是支持中断获取锁。

3、什么是xx锁?Xx锁和yy锁有什么区别?

1)公平锁和非公平锁(fairSync/notFairSync

公平锁:公平的获取锁,按顺序获取锁

非公平锁:与非公平锁相反

2)独占锁和共享锁

独占锁:只有一个线程可以访问;

共享锁:多个线程可以访问;

3)互斥锁和读写锁

互斥锁:reentrantLock

读写锁:read-write-lock

4)乐观锁和悲观锁

乐观锁:乐观,不认为会发生问题,效率会高但实现复杂

悲观锁:认为肯定会发生问题。reentrentLock,Synchronized。效率低,实现简单。

5)偏向锁、轻量级锁、重量级锁

偏向锁——>轻量级锁——>重量级锁 (递增的一个锁的进化状态)

偏向锁:一个代码块, 一直被一个线程所访问。线程就会自动获得锁,降低获得锁的代价

轻量级锁:前提现在的锁是偏向锁,被另一个线程访问。它升级为轻量级锁。

重量级锁:前提,现在是轻量级锁,但是自旋一定次数后,还没有获得这个锁,那么就会进入阻塞状态。这个时候,锁就升级为了重量级锁。

6)重入锁(reentrantLock

7)分段锁 concurrentHashMap

8)自旋锁

不是马上阻塞,而是采用自旋方式,优点:减少上下文切换。缺点:对CPU有很大的消耗。

4、Synchronized

1) Synchronized修饰代码块,对象锁

2) Synchronized修饰方法,对象锁

3) Synchronized 修饰静态方法,类锁

4) Synchronized  修饰类,类锁

5、什么是AQS

AQSAbstractQueuedSynchronizer的简称。也就是抽象队列同步器。基于AQS实现的有reentrantlock,reentrantReadWriteLock,Semaphone,countDownLatch,

cyclicBarrier

一、线程扩展工具类

1、CAS是乐观锁,native方法,三个参数,一个期望的值,一个偏移量,一个要修改的值,如果当前值等于期望值,那就修改成功。

2、CountDownLatch

countDownLatch 是一个多线程控制工具。用来控制线程的等待。设置需要countDown的数量num,然后每一个线程执行完毕之后,调用countDown()方法,而主线程调用await()方法执行等待,直到num个子线程执行了countDown()方法,则主线程开始执行。

3、CyclicBarrier

countDownLatch 非常相似。它支持计数器的反复使用。

CyclicBarrier可以接收一个参数作为barrierAction,每当计数器完成一次技术后——CyclicBarrier.await()时,系统会执行的动作。

4、Semaphore

表示信号量,允许指定数量的线程同时访问某个资源。

acquire()方法用于获得准入许可(如何没有获得成功,则进行等待,直到有线程释放许可而获得该许可为止)

release()用于释放准入许可。

二、AQS源码

1、LockSupport是一个非常好用的线程阻塞工具,它可以在线程内任意位置让线程阻塞。与object.await()方法想比,他不需要获得某个对象的锁,也不会抛出InterruptedException异常

2、Park()可以阻塞当前线程;每个线程有一个许可,该许可默认为不可用,如果该许可是可用状态,那么park()方法会立即返回,消费这个许可。将改许可变为不可用的状态。如果先调用unpark(),使许可证变为可用状态。所以先调用unpark再调用park也不会阻塞。

3、AQS的实现原理是什么?

 

 

 

State表示锁被抢到的次数。加锁+1,释放锁-1

0:表示没有现成占有该锁

1:有线程成功抢到了该锁

2:执行重入锁了,即:某线程自己抢占了两次

N:表示自己抢占了n次锁

 

WaitStatus 状态,1cancell 取消

-1 signal 等待被唤醒

 

2、ReentrantLock

默认是非公平锁,在第一次未抢到锁后,也会去队列里排队,变为公平锁。

 

 

3、加锁流程

 

 

 

 

 

 

 

 

 

posted @ 2021-04-23 20:14  majingyun  阅读(99)  评论(0编辑  收藏  举报