Java中的锁机制

1.在Java中锁的分类

其实就是按照锁的特性分类的

  1. 公平锁,非公平锁
  2. 可重入锁
  3. 独享锁,共享锁
  4. 互斥锁,读写锁
  5. 乐观锁,悲观锁
  6. 分段锁
  7. 偏向锁,轻量级锁,重量级锁
  8. 自旋锁

相关资料:思维导图
使用场景

公平锁,非公平锁

  • 公平锁:是指多个线程按照申请顺序获取锁
  • 非公平锁:是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的先获取,会造成优先级反转或者饥饿现象。

非公平锁的优点是单位时间内吞吐量高,ReentrantLock默认使用非公平锁是基于性能考虑,公平锁为了保证线程规规矩矩地排队,需要增加阻塞和唤醒的时间开销。如果直接插队获取非公平锁,跳过了对队列的处理,速度会更快。

当一个线程请求锁时,会先判断队列中有没有其他线程在等待,然后再判断线程有没有被其他线程占用,如果都没有的话才会获取这个锁,非公平锁则会直接判断这个锁哟没有被占用,没有的话就会直接占用,谓之插队。只有当有线程占用的时候才会排队。

可重入锁

可重入锁表示当前线程获取锁之后,这个线程的其他需要找个锁的操作也能正常执行,
不可重入锁表示当前线程获取这个锁之后,这个线程的其他后续操作不能通过这个锁操作对象。

独享锁,共享锁

  • 独享锁:是指当前锁被该线程获取之后,到锁被释放之前,其他线程都不能获取该锁。
  • 共享锁:是指当前锁可以被多个线程所共有,进行读取。

互斥锁,读写锁

  • 互斥锁:当前线程在获取到这个锁之后,就不能再获得其他的锁,这个所也不能再被其他线程获取,相当于一对一关系,这个线程可以对锁进行读写操作
  • 读写锁:多个读者可以同时进行读,只能有一个写者进行写操作,写者的优先级高于读者,当有写者需要获取锁时,所有读者必须阻塞等待,线程唤醒时优先考虑写者。

乐观锁,悲观锁

  • 乐观锁:默认写操作很少,不会出现同时写的现象,所以写的时候并不会获取锁,只会在提交的时候获取锁,当两个线程同时提交的时候,其中一个线程提交成功,另一个提交失败,异常会返回给上层代码,让他们去处理。
  • 悲观锁:比较悲观的一种态度,认为在对数据操作的时候一定会被修改,所以在整个数据处理规程中,将数据处于锁定状态。悲观锁往往依靠数据库提供的锁机制。

分段锁

  • 分段锁的实现使用的是ConcurrentHashMap,把数据表看做一个大房子,ConcurrentHashMap相当于一个一个房子里有好多小房间,只要有人进了房间就把对应的房间锁起来,其他的还是可以被其他人访问的,HashTable相当于大仓库,只要需要访问其中的数据就要把整个仓库锁起来。

偏向锁,轻量级锁,重量级锁

JavaSynchronized底层实现

原文地址:https://www.cnblogs.com/charlottepl/p/13373065.html