免费制作主图的网站长沙网络推广服务
为什么会有这些锁呢?
因为一种类型的锁很难应对线程操作同步资源的情况。
-
乐观锁和悲观锁
-
自旋锁和适应性自旋锁
-
无锁、偏向锁、轻量级锁和重量级锁
-
公平锁和非公平锁
-
可重入锁和非可重入锁
乐观锁和悲观锁
悲观锁认为当它操作数据的时候,必然用一个线程和它争抢。因此它每一次操作时都会给数据加锁。
乐观锁认为自己在操作数据时,不会有其他线程来操作,所以不加锁,只是在更新的时候判断之前有没有别的线程更新了这个数据。没有更新则写入,更新了则不写入。
自旋锁和适应性自旋锁
自旋锁就是在获取一个资源的时候,判断当前的锁是不是自旋锁,如果是自旋锁,则不放弃cpu时间片,不断地获取资源,直到拿到资源。如果在自旋完成之前,线程释放了资源,当前线程就可以不必阻塞而是直接获取同步资源,从而避免切换线程的开销。这就是自旋锁。
适应性锁说的就是让自旋等待的时间不再固定。当一个线程自旋过后能获取到锁,那么JVM就认为自旋获取锁的概率比较大,会自动增加等待时长。反正,自旋等待很少获取到锁,那么以后要获取这个锁可能省略掉自旋过程,避免资源浪费。
无锁、偏向锁、轻量级锁和重量级锁
偏向锁通过比较Mark Word解决加锁问题,避免执行CAS操作,而轻量级锁通过CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒而影响性能。重量级锁是将除了拥有锁的线程以外的线程都阻塞。
因为阻塞是非常消耗资源的,所以加入了这三种锁机制。最坏的情况是重量级锁。
公平锁和非公平锁
公平锁说的就是按线程请求锁的顺序来获取锁。线程是直接进入队列中排队。
非公平锁说的是多个线程加锁时,会直接尝试获取锁,如果获取不到在进入等待队列的队尾等待。锁如果刚好可用,那么这个线程无需阻塞直接获取锁。
可重入锁和非可重入锁
可重入锁是指在同一个线程在外层方法获取锁的时候,再进入该线程的内层方法会自动获取锁(前提锁对象得是同一个对象或者class),不会因为之前已经获取过还没释放而阻塞。
独享锁和共享锁
独享锁也叫排他锁,是指该锁一次只能被一个线程所持有。如果线程T对数据A加上排它锁后,则其他线程不能再对A加任何类型的锁。获得排它锁的线程即能读数据又能修改数据。JDK中的synchronized和JUC中Lock的实现类就是互斥锁。
共享锁是指该锁可被多个线程所持有。如果线程T对数据A加上共享锁后,则其他线程只能对A再加共享锁,不能加排它锁。获得共享锁的线程只能读数据,不能修改数据。