乐观锁与悲观锁;公平锁与非公平锁
首先来讲讲乐观锁与悲观锁;公平/非公平锁的概念,这两种锁的概念其实是两个维度的,乐观/悲观锁是针对多线程之间数据共享维度的;而公平/非公平锁是多线程执行顺序维度的,一般乐观/悲观锁开发中接触地多一些,下面详细讲一讲:
乐观锁与悲观锁
-
悲观锁(Pessimistic Lock):顾名思义,就是在操作共享数据时,是基于其他线程一定会对该数据进行修改的假设上的,所以一定会阻塞其他线程来保证线程安全。
举例:我们常使用的Synchronized做多线程同步就是悲观锁,具有排他性,缺点就是会容易产生死锁。 -
乐观锁(Optimistic Lock): 与悲观锁相反,但又不是完全想法,乐观锁在读取数据时假设别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制,即对数据做版本控制。所以乐观锁适用于多读的应用类型,这样可以提高吞吐量。
举例:CAS机制(compare and swap),简单来说会有三个操作数,当前内存变量值V,变量预期值A,即将更新值B,当需要更新变量的时候,会直接将变量值V和预期值A进行比较,如果相同,则直接更新为B;如果不相同,则当前变量值V刷新到预期值中,然后重新尝试比较更新。
公平锁与非公平锁
- 公平锁(Fair):加锁前检查是否有排队等待的线程,按照线程加锁的顺序来分配锁的使用权,先来先得。
-
非公平锁(Nonfair):线程加锁时直接尝试获取锁,获取不到就自动到队尾等待。简单来说就是是一种获取锁的抢占机制,是随机获得的锁的。
ReentrantLock锁内部提供了公平锁与分公平锁内部类之分,默认是非公平锁,如下:
//创建一个非公平锁,默认是非公平锁
Lock nonFairLock= new ReentrantLock();
Lock nonFairLock= new ReentrantLock(false);
//创建一个公平锁,构造传参true
Lock fairLock= new ReentrantLock(true);
适用场景:
实际工作中,我们更多的是直接使用非公平锁:非公平锁比公平锁性能高5-10倍,因为公平锁需要在多核情况下维护一个队列,如果当前线程不是队列的第一个无法获取锁,增加了线程切换次数。
网友评论