宣传一下我的qq群:412052579。里面有一些计算机相关的资料,不定期有人开讲。
锁是资源争用模型里面,排队模型的实现方式之一。建议先去了解一下资源争用模型, 临时blog地址
一个锁的设计要考虑的包含如下几个方面:
- 抽象资源状态的标志位
- 对标志位的原子复合操作
- 对争用者行为的控制,包括暂停和恢复
- 对争用者的暂存功能
先理解我说的这四点
然后我再说分布式锁
原子复合操作就是底层工具提供的原子操作的原语
比如jvm给java提供的 cas
cpu给系统提供的内存屏障
硬件到系统,系统到vm,vm到语言,单机到分布式
都相当于底层为上层提供支持
不要傻傻的跟我从语言一步到硬件
系统依赖硬件提供的原子操作(数据结构)构建出系统级原语给vm/c语言用,vm依赖系统提供的原语构造出原子操作(数据结构)给java使用
单机到分布式也是一样的
锁要实现的功能就是要操作排队
操作的划分,在现有的系统中都是以线程为单位的
那么锁要实现的就是让线程排队
排队是做什么呢?我们讲一下生活中的排队
先来的操作资源,后来的人在 依次 等待,等前面的人 完成之后,恢复操作
这句话里有四个重点词语分别是
依次,等待,完成之后,恢复
隐含的一个点就是完成之后怎么通知等待者去操作资源的
我们来说一下这四个关键词
完成之后描述的是资源状态
在锁的设计中,我们一般用一个数字来抽象资源状态
比如0是空闲,1是被占用
依次是要保证线程先来后到的顺序
等待呢,是指不占用cpu
恢复是从排队的队列中唤醒下一个线程
jvm是怎么按照这四点来实现一个锁的呢?
首先用一个state字段抽象资源状态,这个字段是volatile的
然后,利用LockSupport.park功能实现线程等待
将等待的线程放置到CLH队列里
当占用资源的线程使用完成之后,会把state设置为空闲状态,并且利用LockSupport.unpark唤醒下一个线程
马上讲分布式锁
这就是jvm的单机锁
分布式锁与单机锁没有区别,只是资源不再是只存在单机中
也就是说,不是只有单机的线程会争用资源, 其他机器的线程也会争用资源
场景是,一个资源在多机共享
根据以上四点
我们需要一个多机都能读写的state数据
比如用redis来存这个state
然后,就跟单机一个实现线程等待,排队,唤醒
只是这个抽象的状态由多机的线程共同使用了而已
所以还是要先理解争用的资源是什么,争用者的范围是什么
如果争用者范围只是单机的,那么就可以用单机的一个state来抽象争用资源
如果范围是分布式的, 就需要用一个多机都能读写的state来抽象资源状态设计锁
其他的三点,因为都是jvm的线程,所以,都可以利用jvm的原子操作设计
所以,所谓的分布式锁,只是争用者范围扩展了而已
没什么特别的