解决各种锁概念


欢迎访问我的个人博客(点击进入)

各种锁名词解释

1.可重入锁

可重入锁也叫递归锁,指在同一线程中,在外层函数获得锁后,内层的递归函数仍然可以继续获得该锁。在Java环境下Sychronized和ReentrantLock都是可重入锁。

2.公平锁与非公平锁

从字面意义来说,公平锁就是公平的锁,非公平锁就是不公平的锁。

  • 公平锁:指在分配锁之前检查是否有线程在排队的情况,优先分配给等待时间较长的
  • 非公平锁:指在分配锁时不检查是否有现成在排队,直接尝试获得锁(自旋),在获取不到的时候再加入队列

Java中sychronized是非公平锁,ReentrantLock默认为非公平锁

3.读写锁

Java中Lock接口及对象可对对象进行加锁和释放锁,但是这种锁并没有区分读写。为了提高性能,Java提供了读写锁,读写锁分为读锁和写锁两种,多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥。

在系统中并发的读取数据不会涉及到线程安全问题,但是当读和写,写和写在一起是就会出现线程安全问题,数据一致性不能保证。

拿到读写锁的方式:

private final ReentrantReadWriteLock Lock = new ReentrantReadWriteLock();
private final Lock readLock = Lock.readLock();
private final Lock writeLock = Lock.writeLock();

4.共享锁和独占锁

  • 独占锁:也叫互斥锁,每次只有一个线程可以拥有这个锁,如synchronized和ReentrantLock
  • 共享锁:允许多个线程同时持有该锁,并发的访问共享资源,如读锁

独占锁是一个悲观的加锁策略,同一时刻只允许一个线程访问共享资源,限制了读锁的并发性;因为并发读取并不会影响数据的一致性。

共享锁是一个乐观的加锁策略,允许多个执行读操作的线程同时访问共享资源。

5.重量级锁和轻量级锁

  • 重量级锁是基于操作系统互斥量而实现的锁,会导致进程在用户态和内核态不断切换,开销较大
  • 轻量级锁是相对重量级锁而言的,核心涉及是在没有多线程竞争的情况下, 减少重量级锁的使用以提高系统性能。适用于线程交替执行同步代码块的情况吗,当有多线程竞争同一个锁时会膨胀为重量级锁。

JDK1.6版本后,为了减少sychronized带来的性能损耗,引入了轻量级锁,偏向锁,适应自旋,锁消除,锁粗化。

6.偏向锁

除了多线程竞争同一锁的情况,还会出现同一个锁被同一个线程多次获取的情况。偏向锁用于某个线程多次获取同一个锁,消除这个线程锁重入的开销,看起来像是这个线程得到了偏袒。

偏向锁的主要目的是在同一个线程多次获得某个锁的情况下尽量减少轻量级锁的执行路径,因为轻量级锁的获取及释放需要多次CAS操作,而偏向锁只需要在切换ThreadID时执行一次CAS操作。

在出现多线程竞争同一锁的情况下,JVM会自动撤销偏向锁。

轻量级锁用于提高线程交替执行同步代码块的性能,偏向锁用于提高某个线程交替执行同步块时进一步提高性能。

锁的状态共有4种:无锁,偏向锁,轻量级锁,重量级锁。随着锁竞争越来越激烈,锁可能逐渐升级。

7.分段锁

并不是真实锁,而是一种思想。用以将数据分段并在每个分段上都加上锁,把锁进一步细粒度化,以提高并发效率。ConcurrentHashMap在内部就是这样实现的。

8.同步锁和死锁

在有多个线程被同时被阻塞时,它们之间若相互等待对方释放锁资源,就会出现死锁。为了避免死锁,可以为锁操作添加超时时间,在线程池有锁超时后自动释放该锁。

9.如何进行锁优化

  1. 减少锁持有的时间:只在有线程安全要求的程序上加锁来尽量减少同步代码块对锁持有的时间
  2. 减小锁粒度:将单个耗时较多的锁拆分为多个耗时较少的锁来增加锁的并行度,减少同一个锁的竞争。锁竞争减少后偏向锁,轻量级锁的使用率才会提高
  3. 锁分离:根据不同应用场景将锁的功能进行分离,以应对不同的变化。如读写锁
  4. 锁粗化:为了保障性能会尽量要求锁的操作细化以减少线程持有锁的时间。锁如果分的太细,将会导致系统频繁获取锁和释放锁,影响系统性能
  5. 锁消除:消除不用的锁

你可能感兴趣的:(JUC)