一文彻底搞懂面试中常问的各种“锁”

4次阅读

共计 1939 个字符,预计需要花费 5 分钟才能阅读完成。

前言
锁,顾名思义就是锁住一些资源,当只有我们拿到钥匙的时候,才能操作锁住的资源。在我们的 Java,数据库,还有一些分布式的环境中,总是充斥着各种各样的锁让人头疼,例如“公平锁”、“自旋锁”、“读写锁”、“分布式锁”等等。
其实真实的情况是,锁并没有那么多,很多概念只是从不同的功能特性,设计,以及锁的状态这些不同的侧重点来说明的,因此我们可以根据不同的分类来搞明白为什么会有这些“锁”?坐稳扶好了,准备开车。
正文
“公平锁”与“非公平锁”
公平锁: 指线程在等待获取同一个锁的时候,是严格按照申请锁的时间顺序来进行的,这就意味着在程序正常运作的时候,不会有线程执行不到,而被“饿死”,但是也需要额外的机制来维护这种顺序,所以效率相对于非公平锁会差点。
非公平锁:概念跟“公平锁”恰恰相反,随机线程获取锁,相率相对高。
new ReentrantLock(); // 默认非公平锁
new ReentrantLock(true); // 公平锁
“重入锁 (递归锁)”与“不可重入锁(自旋锁)”
这里要注意了,重入 / 递归,不可重入 / 自旋,虽然名字不同,但是确实是同一种锁,只是从锁的表现跟实现方式的角度来命名而已。
重入锁:当一个线程获取了 A 锁以后,若后续方法运行被 A 锁锁住的话,当前线程也是可以直接进入的。
public class Demo {
private Lock lockA;

public Demo(Lock Lock) {
this.lockA = lock;
}

public void methodA() {
lockA.lock();
methodB();
lockA.unlock();
}

public void methodB() {
lockA.lock();
//dosm
lockA.unlock();
}

}
当我们运行 methodA() 的时候,线程获取了 lockA,然后调用 methodB() 的时候发现也需要 lockA,由于这是一个可重入锁,所以当前线程也是可以直接进入的。在 java 中,synchronized 跟 ReetrantLock 都是可重入锁。
不可重入锁:以上面的代码实例来说明,就是 methodA 进入 methodB 的时候不能直接获取锁,必须先调用 unLock 释放锁。才能执行下去,那实现不可重入锁有什么方式呢?那就是自旋,所以会有一个小名叫做自旋锁。
public class SpinLock {

private AtomicReference<Thread> sign =new AtomicReference<>();

public void lock(){
Thread current = Thread.currentThread();
while(!sign .compareAndSet(null, current)){
}
}

public void unlock (){
Thread current = Thread.currentThread();
sign .compareAndSet(current, null);
}
}
“悲观锁”与“乐观锁”
这两种锁呢,其实是一个很宏观的分类,它不是一种具体的锁,而是泛指看待并发的程度。
悲观锁:有一个“悲观”的心态,既每次取数据的时候,都会认为该数据会被修改,所以必须加一把锁才安心。
乐观锁:乐观的孩子,认为同一个数据不会发生并发操作的行为,所以取的时候不会加锁,只有在更新的时候,会通过例如版本号之类的来判断是否数据被修改了。
Java 中各种锁其实都是悲观锁的实现,既操作的数据的都会被获取锁的线程锁住,而乐观锁的话,一般是通过 cas(compare and swap)的思想来实现,例如一些原子类 AtomicInteger 使用自旋来原子更新。
“共享锁”与“排他锁”
这两种锁的概念比较多的出现在数据库的事务当中。
共享锁:也称读锁或 S 锁。如果事务对数据 A 加上共享锁后,则其他事务只能对 A 再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据。在 java 中的 ReetrantReadWriteLock() 也是如此。
排它锁:也称独占锁、写锁或 X 锁。如果事务对数据 A 加上排它锁后,则其他事务不能再对 A 加任何类型的锁。获得排它锁的事务即能读数据又能修改数据。
分布式锁
我们上面聊的这些锁,都是在单个程序上面的不同线程之间来实现的,那么当我们的不同程序需要去竞争同一块资源的时候,这就需要分布式锁了,我们可以通过 redis、zookeeper 等中间件来实现分布式锁。
对于锁来说,其实还有偏向锁,轻量级锁等,但是这里涉及到的内容就比较多,这里就不在展开篇幅介绍了,有兴趣的同学可自行研究,如果你能搞懂上面介绍的这些锁,那基本上在绝大部分的公司关于“锁”的问题都可以迎刃而解。
文章首发于微信公众号《深夜里的程序猿》,转载务必注明出处,侵权必究。

正文完
 0