1.公平锁/非公平锁
公平锁FairSync:多个线程按照申请锁的顺序获取锁
非公平锁NonfairSync:多个线程获取锁的顺序不是按照申请锁的顺序,有可能后申请的线程会比先申请的线程优先获取锁,有可能造成优先级反转和饥饿现象
但是,非公平锁吞吐量比公平锁大:
ReentrantLock的默认构造是非公平锁,可以在构造中写true变成公平锁
Synchronized也是非公平锁,由于其并不像ReentrantLock是通过AQS的来实现线程调度,所以并没有任何办法使其变成公平锁。
2.可重入锁(递归锁)
可重复递归的调用锁,同一个线程在外层函数锁的时候,在内层递归函数也可以获取锁,并且不发生死锁(前提是同一个对象或者class) 也就是说:线程可以进入任何一个它已经拥有的锁所同步着的代码块
ReentrantLock和synchronized都是可重入锁
3.独占锁/共享锁
独占锁:该锁一次只能被一个线程持有
ReentrantLock和Synchronized都是独占锁
ReentrantWriteLock是独占锁
共享锁:锁可以被多个线程共有
ReentrantReadLock的读锁是共享锁,
4.互斥锁/读写锁
上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。
互斥锁在Java中的具体实现就是ReentrantLock
读写锁在Java中的具体实现就是ReadWriteLock
5.乐观锁/悲观锁
悲观锁:总是假设最坏的情况,每次去拿数据都会认为别人会修改,所以在拿数据时都会上锁,别人想要拿到这个数据就会阻塞,直到他拿到锁为止,传统的关系型数据库就用到了很多这种锁机制,比如:行锁,表锁,读锁,写锁等,都是在操作前先上锁,Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
乐观锁:总是假设最好的情况,每次去拿数据都认为别人不会修改,所以不会上锁,但是在更新的时候会判断别人在此期间有没有更新这个数据,可以使用CAS和版本号来实现,乐观锁适合多读的应用类型,可以提高吞吐量
6.分段锁
分段锁其实是一种锁的设计,并不是具体的锁,对于ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。
并发容器类的加锁机制是基于粒度更小的分段锁,分段锁也是提升多并发程序性能的重要手段之一。
在并发程序中,串行操作是会降低可伸缩性,并且上下文切换也会减低性能。在锁上发生竞争时将通通导致这两种问题,使用独占锁时保护受限资源的时候,基本上是采用串行方式—-每次只能有一个线程能访问它。所以对于可伸缩性来说最大的威胁就是独占锁。
7.偏向锁/轻量级锁/重量级锁
这三种锁是指锁的状态,并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。
偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。
8.自旋锁
在Java中,自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。
本文介绍了Java中的多种锁机制,包括公平锁与非公平锁的概念,可重入锁(递归锁)的特性,独占锁与共享锁的差异,互斥锁和读写锁的实现,乐观锁与悲观锁的工作原理,分段锁在并发容器如ConcurrentHashMap中的应用,以及Java锁的三个状态:偏向锁、轻量级锁和重量级锁的详细解释。此外,还提到了自旋锁及其在提高并发性能中的作用。
170万+

被折叠的 条评论
为什么被折叠?



