公平锁/非公平锁
公平锁:多个线程按照申请锁的顺序来获取锁
非公平锁:指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁.
对于ReentrantLock来说.其构造函数可以指定该锁是否为公平锁,默认非公平锁,其优点是吞吐量大,Synchronized也是非公平锁.
可重入锁(递归锁)
在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁.(ReentrantLock和Synchronized都是递归锁),其优点是可一定程度避免死锁.
独享锁/共享锁
独享锁:指该锁一次只能被一个线程所持有.
共享锁:指该锁可以被多个线程所持有.
ReentrantLock和Synchronized都是独享锁,ReadWriteLock中的读锁是共享锁,写锁是独享锁.
互斥锁(ReentrantLock)/读写锁(ReadWriteLock)
ReentrantReadWriteLock是不支持锁升级:从读锁变成写锁
ReentrantReadWriteLock支持锁降级:从写锁变成读锁
从写锁降级成读锁,并不会自动释放当前线程获取的写锁,仍然需要手动释放
sql中的常用锁:
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。
乐观锁(原子类)/悲观锁(指看待并发同步的角度)
乐观锁:认为对于同一个数据的并发操作,是不会发生修改的,因此不会锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据.多用于读的应用类型
悲观锁:总是假设最坏的情况,每次拿数据都认为别人会修改,因此每次拿数据的时候都会上锁,别人想拿这个数据就会阻塞,直到拿到锁.
分段锁:
其实是一种锁的设计,如ConcurrentHashMap中的Segment,当需要put元素的时候,并不是对整个HashMap进行加锁,而是先通过HashCode来知道他要放在哪一个分段,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行.分段锁的设计目的是细化锁的粒度.
偏向锁/轻量级锁/重量级锁
偏向锁:指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁,降低获取锁的代价.
轻量级锁:指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级成轻量级锁.其他线程会通过自旋的形式尝试获取锁.不会阻塞,提高性能.
重量级锁:指当锁是轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数以后,还没有获取到锁,就会阻塞,该锁膨胀为阻塞,重量级锁会让其他申请的线程进入阻塞,性能降低.
自旋锁:指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,自旋锁省去了阻塞锁的时间空间开销,但长时间自旋就变成了忙式等待,忙式等待还不如自旋,因此自旋的次数一般控制在一个范围内.
synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致死锁的出现.