锁种类以及具体实现

锁种类以及具体实现

乐观锁 VS 悲观锁

乐观锁:在Java中是通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的。

悲观锁:synchronized关键字和Lock的实现类。

  • 悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。
  • 乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。

自旋锁 VS 适应性自旋锁

自旋锁:实现原理同样也是CAS,AtomicInteger中调用unsafe进行自增操作的源码中的do-while循环就是一个自旋操作,如果修改数值失败则通过循环来执行自旋,直至修改成功。

适应性自旋锁:自适应意味着自旋的时间(次数)不再固定

无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁

无锁的特点就是修改操作在循环内进行,线程会不断的尝试修改共享资源。如果没有冲突就修改成功并退出,否则就会继续循环尝试。如果有多个线程修改同一个值,必定会有一个线程能修改成功,而其他修改失败的线程会不断重试直到修改成功。上面我们介绍的CAS原理及应用即是无锁的实现。无锁无法全面代替有锁,但无锁在某些场合下的性能是非常高的。

偏向锁通过对比Mark Word解决加锁问题,避免执行CAS操作。而轻量级锁是通过用CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞。

公平锁 VS 非公平锁

可重入锁 VS 非可重入锁

ReentrantLock内部实现了公平锁和非公平锁(同时也是可重入锁)。

synchronized也是可重入锁。

非可重入锁:NonReentrantLock。(加锁的时候直接尝试获取,要么成功要么直接失败;释放锁,直接将status置为0。

独享锁 VS 共享锁

独享锁也叫排他锁,是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排它锁后,则其他线程不能再对A加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。(synchronized和ReentrantLock)

共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。(ReentrantReadWriteLock的读锁)


锁种类以及具体实现
http://www.muzili.ren/2022/06/11/锁种类及其具体实现/
作者
jievhaha
发布于
2022年6月11日
许可协议