一、悲观锁和乐观锁
(1)乐观锁
乐观锁假定被加锁的数据或者代码段在之后的运行中,锁冲突很少或者没有,加上乐观锁并不会直接就加锁,避免过多的加锁操作。
一种实现方式:
在使用乐观锁加锁时,不会直接加锁,而是首先取得现在加锁数据的状态,然后在需要修改被加锁的数据的时候,比较此时的数据和刚刚加锁时取得的数据是否相等,相等则说明没有其他线程对加锁数据进行修改,此线程就直接修改数据,不相等则说明其他线程在这期间修改了这个数据,此时就进行回滚,重新尝试修改数据。
(2)悲观锁
悲观锁假定被加锁的数据之后锁冲突会非常激烈,每次加锁就直接进行加锁,其他线程想要加锁就只能阻塞等待。
二、重量锁和轻量锁
重量锁加锁和解锁开销大,轻量锁加锁和解锁开销小。
一般情况下,乐观锁也是轻量锁,悲观锁也是重量锁。
三、自旋锁和挂起等待锁
(1)挂起等待锁
一个线程申请锁时,发生了锁竞争,此时这个线程直接就挂起等待,知道这个锁被释放并且唤醒了这个线程,这个锁才能被这个线程申请到。
(1)自旋锁
一个线程申请锁,也发生了锁竞争,但是这个线程不会阻塞等待,而是不停的循环判断它申请的这个锁是否被释放,直到释放了之后,它马上加锁进行后面的操作。
自旋锁是一种典型的轻量锁,挂起等待锁是一种典型的重量锁。
四、互斥锁和读写锁
(1)互斥锁
就是一个把锁只能被一个线程加锁,另一个线程想要加锁只能等待。
(2)读写锁
读写锁的并不是所有加锁冲突都互斥,只有读写互斥和写写互斥,读读是不互斥的,也就是就算加了读锁之后,其他线程要加读锁也可以继续加。
五、公平锁和非公平锁
(1)公平锁
每次释放锁后,下一个获得锁的是阻塞时长最长的线程。
(2)非公平锁
每次释放锁后,下一个获得锁的是随机的一个阻塞线程。
六、可重入锁和不可重入锁
不可重入就是同一个线程不可以对一个锁重复加锁,会出现加了一个锁之后,此时还要再加一次这个锁,但是这个锁之前已经被这个线程获取了,此时第二次就获取不到这个锁,产生了死锁。
可重入锁就不会可以重复对这个锁加锁,不会出现这样的死锁情况。