应用层|关于编程语言中的那些「锁」事
并发锁,在编程语言中并不陌生。不同的语言中,锁的使用大同小异,以 Java 语言中的锁最为典型。我们今天就从什么是锁、我们为什么需要锁、锁的分类、有关锁的应用这四个方面,一起来聊聊与锁有关的那些事。
在日常生活中,锁就是一个安全标志。我们通过上锁和解锁,实现安全离家和回家。在编程语言中,锁也是个安全标志。在多线程并发场景下,给某个变量,或某个方法函数加个锁,代表同一时刻只能有一个线程访问该变量或者该方法函数。同时它又是在许多面试场景中经常会被面试官问到的,接下来结合例子来和大家讨论下悲观锁与乐观锁。
先讲概念太枯燥,所以我们举一个通用的生活场景作为例子。A 和 B 两个人分别去车站买从上海到北京的同一时间出发的高铁票。A 排队在 1 号售票窗,B 排队在 2 号售票窗,两人同时递出身份证买票,好巧不巧,1 和 2 号窗口的售票员同时说这班车只有一张票,怎么办?拼哪个窗口的售票员手速更快吗?于是 A 和 B 就开始吵架,可后面排队的很多人都在等。如果 A 和 B 继续吵架僵持不下,就会连带着浪费其他人的时间。经过讨论,大家一致认为,即便是要拼手速也是他俩拼。那么问题来了,用什么来拼呢?这个时候,站长出来了。他说,我这里有一把锁,会放在你们中间的位置上,谁抢到就先给谁买票,这样对 A 和 B 都公平。大家一阵欢呼,一把锁解决了抢票的纷争。这个场景放在编程语言中,就是一个典型的多线程并发场景问题。上述的 A 和 B 是两个线程,高铁票则可以看作是一个变量或者一个方法函数。如果不加锁,高铁票就会被 A 和 B 抢来抢去,变得面目全非,甚至还会出现一开始票价为 50 元,结果抢着抢着可能就被人把价格改到了 100 元。所以,给高铁票(变量或方法函数)加一个锁,谁抢到锁,就有权使用该高铁票(变量或方法函数),保证其安全。
a.线程是否给同步资源加锁?
是:悲观锁。
否:乐观锁。
b.同步资源加锁失败,线程是否需要阻塞?
是:阻塞。
否:不阻塞(自旋锁、适应性自旋锁)。
c.多个线程竞争同步资源的细节区别是?
无锁:不锁住资源,多个线程中只有一个能修改资源成功,其它线程会重试。
偏向锁:同一个线程执行同步资源时自动获取资源。
轻量级锁:多个线程竞争同步资源时,没有获取资源的线程自旋等待锁释放。
重量级锁:多个线程竞争同步资源时,没有获取资源的线程阻塞等待唤醒。
d.多个线程竞争锁时要不要排队?
排队:公平锁。
先尝试插队,插队失败再排队:非公平锁。
e.一个线程中的多个流程能不能获取同一把锁?
能:可重入锁。
不能:非可重入锁。
f.多个线程能否共享一把锁?
能:共享锁。
不能:排他锁
为了方便扣友们理解,下面将以乐观锁和悲观锁为例,简单说下锁的应用场景。
乐观锁和悲观锁
先说概念。悲观锁,从这个名字我们就能看出,这个锁的态度是比较悲观的,它会认为自己在使用变量或者方法的同时,一定会有其他的线程来跟它抢,所以,他最爱做的事情就是先加锁。等它使用完,别的线程想做啥就做,手中有锁,并发不愁。
而乐观锁呢,和悲观锁截然不同。它的态度很乐观,每次使用前,它都认为不会有别的线程跟它抢,所以每次都不会加锁,只是在更新某个数据时,才会去判断之前有没有别的线程更新这个数据。如果这个数据没有被更新,当前线程会将自己修改的数据成功写入。如果数据已经被其他线程更新,它就会根据不同的实现方式执行不同的操作(例如报错或者自动重试)。
从两者概念的不同,我们就会知道两者所适合应用的场景也是不一样的。悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。光说概念有些抽象,我们来看下乐观锁和悲观锁的调用方式例子:
//--悲观锁的调用方式--
//synchronized
public synchronized void testMethod(){
...具体方法省略...
}
//ReentrantLock
private ReentrantLock lock = new ReentrantLock();//需要保证多个线程
使用的是同一个锁
public void modifyPublicResources(){
lock.lock();
...具体方法省略...
lock.unlock();
}
//--乐观锁的调用方式--
private AtomicInteger atomicInteger = new AtomicInteger();//
需要保证多个线程使用的是同一个AtomicInteger
atomicInteger.incrementAndGet();//执行自增1
那么,为什么乐观锁能够做到事先不加锁也可以正确的实现线程并发呢?这就涉及到乐观锁的主要实现方式“CAS”的技术原理了,感兴趣的扣友们可以留言,可以再开一篇来给大家聊聊。你们在工作中还遇到过哪些锁,有没有遇到过被锁耽误头秃的时候,也欢迎大家在评论区积极留言~
BY /
本文作者:海洋
编辑&版式:Janson
声明:本文归“力扣”版权所有,如需转载请联系。
点个在看,少个 bug
微信扫码关注该文公众号作者