Java并发场景里的各种锁

Java并发场景里的各种锁插图

一、独享锁 VS 共享锁

1、独享锁

是指该锁一次只能被一个线程所持有,如下图所示:

Java并发场景里的各种锁插图2

2、共享锁

共享锁是指该锁可被多个线程所持有,如下图所示:

Java并发场景里的各种锁插图4

这样设计的原因是就是尽最大的解放并发读的操作,因为读占据了更大的访问请求,我只会在涉及少部分写的操作的时候才考虑独享锁,从而提升并发的效率。

二、乐观锁 VS 悲观锁

悲观锁 VS 悲观锁,在Java并发编程和数据库中都有实际的应用场景。

1、悲观锁

悲观锁它认为在它修改数据之前,一定会有其它线程去修改它,所以每次在拿数据的时候都会上锁。

典型代表就是一篇我谈到的Synchronized的底层实现原理,就是典型的悲观锁。

2、乐观锁

乐观锁,顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改。

如下图所示:

Java并发场景里的各种锁插图6

比如典型的应用就是Java并发里的CAS实现,Java并发包中的很多类都使用了CAS技术来实现乐观锁。

CAS全称 Compare And Swap,即比较与交换,就是一种乐观锁算法。

三、公平锁 VS 非公平锁

1、公平锁

公平锁,就是很公平,在并发环境中会按照FIFO的规则来获取锁。

如下图所示:

Java并发场景里的各种锁插图8

Java并发编程里ReentrantLock,可以指定构造函数来创建公平锁。

比如:

new ReentrantLock(true)

2、非公平锁

非公平锁就是不用正常排队来获取锁,而是上来就直接尝试占有锁。

如下图所示:

Java并发场景里的各种锁插图10

1)非公平锁的优点

优点:就是可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁。

2)非公平锁的缺点

缺点就是:处于等待队列中的线程可能会饿死,或者等很久才会获得锁。

3)非公平锁的应用

ReentrantLock的构造函数的默认就是采用非公平锁的实现。

如下所示:

new ReentrantLock(false)

也就是说ReentrantLock里面就包含了两种锁的实现:默认就是非公平锁,可以通过修改设置true从而变成公平锁。

发表评论