专注于快乐的事情

锁的基本概念

锁的学习

锁的出现

最早出现在操作系统中,用于进程和线程间的同步

临界区概念
一个进程在进入临界区之间,必须得到锁。

1
2
3
4
5
6
7
8
9
While(true) {

请求锁
临界区

释放锁
剩余区

}

信号量作为同步工具
锁是同步的一种,2值信号量就是一个互斥锁

锁的分类

根据锁只能被单个线程持有还是能被多个线程共同持有,锁可以分为独占锁和共享锁。

独占锁(排它锁、互斥锁、写锁、X锁)

独占锁保证任何时候都只有一个线程能得到锁,ReentrantLock就是以独占方式实现的。还有如java的内置锁( synchronized)

如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的锁,直到在事务的末尾将资源上的锁释放为止。
锁在一个时间点只能被一个线程锁占有。根据锁的获取机制,它又划分为“公平锁”和“非公平锁”。

共享锁(读锁、S锁)

共享锁则可以同时由多个线程持有,例如ReadWriteLock读写锁,它允许一个资源可以被多线程同时进行读操作。

如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排他锁,直到已释放所有共享锁。获准共享锁的事务只能读数据,不能修改数据
能被多个线程同时拥有,能被共享的锁。

其他纬度的分类

可重入锁

如果锁具备可重入性,则称作为可重入锁。也就是说,锁可以被单个线程多次获取。
当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2,synchronized和ReentrantLock都是可重入锁。

可中断锁

如果某一线程A正在执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。

公平锁

公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待时间最久的线程(最先请求的线程)会获得该所,这种就是公平锁。

在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序, ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。
例如ReentrantLock pairLock = new ReentrantLock(true)

自旋锁

自旋锁则是,当前线程在获取锁时,如果发现锁已经被其他线程占有,它不马上阻塞自己,在不放弃CPU使用权的情况下,多次尝试获取(默认次数是10,可以使用-XX:PreBlockSpinsh参数设置该值)。
如果尝试指定的次数后仍没有获取到锁则当前线程才会被阻塞挂起。

不同视角

数据库系统的角度

锁分为以下三种类型。独占锁,共享锁,更新锁

从程序员的角度看

乐观锁(Optimistic Lock)
乐观锁的概念,他的核心思路就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。常见的乐观锁技术(CAS),乐观锁,是一种无锁方案。

悲观锁(Pessimistic Lock)
需要程序员直接管理数据或对象上的加锁处理,并负责获取、共享和放弃正在使用的数据上的任何锁。

悲观锁,也是基于数据库的锁机制实现。

评论系统未开启,无法评论!