面试必问的多线程-1.4:各种锁介绍

认识的锁?

偏向锁

轻量级锁

重量级锁

重入锁

自旋锁

共享锁

独占锁\排它锁

读写锁

公平锁

非公平锁

死锁

活锁

1:偏向锁

是Java6引入的一项多线程优化,它会偏向于第一个访问锁的线程,

如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。

如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

2:轻量级锁

轻量级锁是由偏向所升级来的,偏向锁运行在一个线程进入同步块的情况下,当第二个线程加入锁争用的时候,偏向锁就会升级为轻量级锁。

3:重量级锁

重量级锁:等待锁的线程会被阻塞。这种方式的成本非常高,因此后来称这种锁为“重量级锁”。synchronized就属于这种锁。

4:重入锁

重入锁(ReentrantLock是一种递归无阻塞的同步机制。重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。

在JAVA环境下 ReentrantLock 和synchronized 都是可重入锁。

也就是说在一个synchronized方法或块的内部调用本类的其他synchronized方法或块时,是永远可以得到锁的。

 

可重入锁指的是在一个线程中可以多次获取同一把锁,

比如:

一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法,而无需重新获得锁;

Java中锁的粒度是线程级别的,也就是说当线程持有某一个对象的锁的时候,该线程可以再次获取该对象的锁,从而进入同步代码块。JVM会为每一个锁维持一个计数器。每当被获取时计数器加1,退出代码块时-1,当计数器为0时,锁将被释放。

 

其实重入锁很好理解:

也就是当一个线程获取多次锁的时候,可以给他获取。

如果当前进来的线程和当前保存锁的线程是同一个线程,

则可以拿到锁,

但是有代价的,

更新状态值state+1,

释放锁则-1,

直到为0,才是真正的释放该对象的锁。

ReentrantLock和synchronized都是重入锁。

可重入锁最大的作用是避免死锁。

5:自旋锁

自旋锁,由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。如何旋转呢?何为自旋锁,就是如果发现锁定了,不是睡眠等待,而是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时才能进入临界区。

如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,只需让线程执行一个忙循环(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。

自旋等待不能代替阻塞,自旋等待本身虽然避免了线程切换的开销,但是要占用处理器时间,因此如果锁被占用时间很短,自旋等待效果就会非常好,但如果锁被占用的时间很长,那么自旋的线程只会白白消耗处理器资源,不会有任何有用的工作,反而会带来性能上的浪费。

6:共享锁-排他锁(独占锁)

若某事务在数据上持有独占锁定(X), 则其他会话不能读写数据,其他事务不能对该数据持有任意类型的锁。

若某事务在数据上持有共享锁(S),则其他会话只能读取数据、不能写数据,其他事务只能申请对该数据的共享锁、而不能申请独占锁。

排它锁:在同一时刻,只允许一个线程进行访问

如:synchronized

共享锁:在同一时刻,允许多个读线程同时进行读。

7:读写锁

读写锁分为读锁和写锁两个

读锁:是一个共享锁,它可以同时被多个线程同时进入

写锁:是一个排他锁,同一个时刻只能有一个写线程进入

只有读和读不互斥,其他都互斥(读和写-写和写)

读写锁:接口:ReadWriteLock 实现类:ReentrantReadWriteLock

8:公平锁-非公平锁

公平是针对锁的获取而言的,(有一个锁的等待队列,按照FIFO的规则)

如果一个锁是公平的,

那么锁的获取顺序就应该符合请求的绝对时间顺序。

其实就相当于排队,一个一个的来,按照先来后到的顺序,来进行获取锁。

非公平锁:

就相当于一个窗口大家一起抢,谁抢到就是谁的。

ReentrantLock 也是实现了公平的,他也是公平的。

 ReentrantLock  创建公平锁和非公平锁(默认)

9:死锁-活锁

死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。死锁发生的四个条件

活锁:是指线程1可以使用资源,但它很礼貌,让其他线程先使用资源,线程2也可以使用资源,但它很绅士,也让其他线程先使用资源。这样你让我,我让你,最后两个线程都无法使用资源。

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/u010953880/article/details/87934244
今日推荐