PART1:让我自己考虑实现乐观锁&悲观锁
- 悲观锁:认为什么时候都有可能出问题,无论做什么都会加锁
- 一个线程拥有(获得)悲观锁后,其他任何线程都不能对数据进行修改啦,只能等待锁被释放才可以执行,
就是说不管怎样我都觉得你会出问题,所以我要给你加锁
- SQL语句select …for update就是悲观锁的一种实现
- Java的synchronized关键字也是悲观锁的一种体现。synchronized和ReentranLock等都是悲观锁思想的体现
- 一个线程拥有(获得)悲观锁后,其他任何线程都不能对数据进行修改啦,只能等待锁被释放才可以执行,
- 乐观锁:认为什么时候都不会出问题,乐观锁的很乐观,它认为数据的变动不会太频繁,操作时一般都不会产生并发问题。所以不用加锁。更新数据的时候去判断一下看看在此期间是否有人修改过数据
- 因此,乐观锁不会上锁,
乐观锁只是在更新数据时,再去判断其他线程在这之前有没有对数据进行过修改
。乐观锁一般会使用版本号机制或CAS算法实现【CAS(Compare and Swap 比较并交换)就是乐观锁的一种实现方式。】
。
- 因此,乐观锁不会上锁,
PART2-0:Redis实现分布式锁【实现分布式锁,用zookeeper最好
】
- setnx
- 缺点就是:时间到了,操作没执行完怎么办【
这哥们没写完呢时间到了,另一个哥们往进写,不就相当于写入脏数据了嘛
】- 此时可以使用多线程或者说守护线程,加上过期时间这个思路,用来延长过期时间,可以用redisson
- 缺点就是:时间到了,操作没执行完怎么办【
PART2-1:Redis实现乐观锁(监控):watch
- JUC中的自旋锁就可以实现这种功能
- 监视器:通过执行MONITOR命令,客户端可以将自己变为一个监视器(发送MONITOR命令可以让一个普通客户端变为一个监视器,这个客户端的REDIS_MONITOR标志会被打开,并且这个客户端本身会 被添加到monitors链表的表尾。),实时地接收并打印出服务器当前处理的命令请求的相关信息:
每当一个客户端向服务器发送一条命令请求时,服务器除了会处理这条命令请求之外,还会将关于这条命令请求的信息发送给所有监视器
- 向监视器发送命令信息: 服务器在每次处理命令请求之前,都会调用replicationFeedMonitors 函数,由这个函数将被处理的命令请求的相关信息发送给各个监视器。
当一个客户端从普通客户端变为监视器时,该客户端的REDIS_MONITOR标识会被打开
- 服务器将所有监视器都记录在monitors链表中。
- 每次处理命令请求时,服务器都会遍历monitors链表,将相关信息发送给监视器。
巨人的肩膀:
Redis设计与实现
redis中文官方文档