java中锁的产生,是由于硬件的发展,以及多核处理器的产生。
在单机模式下,内存区域是共享的,早期一个处理器,所有线程都需要排队处理,也就意味着在任何一个时间点,有且仅有一个线程在执行。在这种串行模式下,是没有并发问题的。但是随着硬件技术的不断发展,处理器更新为多核,这也就意味着同一个时间点,有多个线程同时在被处理,当这多个线程操作同一块内存时,就会出现数据一致性的问题。
并发实质是对可见性、原子性、有序性的处理。导致可见性bug的原因是缓存,导致有序性bug的原因是编译优化。对此,java本身提供了volatile、synchronized和final三个关键字和happens-before规则,来解决上述问题。
Happens-Before的7个规则:
Happens-Before的1个特性:传递性。
底层是依赖JVM来实现,通过对象头中添加标记,来保证线程的阻塞。
当多个线程同时请求同一个对象的锁时,通过Contention List、Entry List、Wait Set来完成线程的阻塞。
自旋锁:在线程进入Contention List时,首先会进行自旋尝试获取锁,不成功进入等待队列。这个时候,自旋锁的线程会和entry list中的ready线程一起抢占锁,导致已经等待的线程不公平。但是由于自旋可以减小线程在用户态和内核态的频繁切换,提高效率。
偏向锁:为了解决在无竞争情况下锁性能问题。前提是锁必须是可重入锁,已经获得该对象的锁的线程再次进入锁的时候,通过已有变量直接进入。(上述的队列会出现CAS操作,例如进入Contention List的时候)。
底层是直接依赖处理器来完成。所有请求线程在一个CLH队列中,当一个线程执行完毕(lock.unlock())时会激活自己的后继节点,但正在执行的线程并不在队列中,而那些等待执行的线程全部处于阻塞状态,等待线程的显式阻塞是通过调用LockSupport.park()完成,而LockSupport.park()则调用sun.misc.Unsafe.park()本地方法,再进一步,HotSpot在Linux中中通过调用pthread_mutex_lock函数把线程交给系统内核进行阻塞。
tryAccquire来完成锁竞争
state状态值表示锁是否被占用,以及支持锁的重入和偏向(Sync.nonfairTryAcquire)
通过将调用线程封装成链表,通过前继节点来判断当前节点是否应该被阻塞。节点保存了当前线程的状态。
当锁被释放release()的时候,会触发链表的head线程来争取锁。但是这个竞争过程也可能被刚进入的线程提前获取锁。
解锁的时候通过tryRelease()方法来讲state置为0,由于没有其他线程,所以不需要CAS。
信号量,用于多线程之间的线程编排(线程阻塞,唤醒等依赖于lock),效力类似于wait()/notify()。
相比较wait()/notify(),condition更加灵活,能更加精准控制线程。但是当线程编排业务复杂时候,condition编写起来就会比较复杂。
//获取信号量
Condition condition = lock.newCondition();
while(!redisTempLate.setNX(key,value,time)){}
通过自旋来阻塞线程获取锁。
对key添加过期时间来避免死锁。
对于公平性,可以通过FIFo的队列来管理线程
集群情况下,会出现数据的一致性问题,集群情况下采用Redlock算法。
大致思想即为:每个客户端对某个方法加锁时,在zookeeper上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点。 判断是否获取锁的方式很简单,只需要判断有序节点中序号最小的一个。 当释放锁的时候,只需将这个瞬时节点删除即可。同时,其可以避免服务宕机导致的锁无法释放,而产生的死锁问题
节点存储主机信息,可以保证数据的可重入。
节点是有序的,可以通过节点的顺序来保证锁的公平性,通过上述的主机信息来通知线程。
对zk的加锁解锁操作,都需要leader来完成,以便保证集群数据的一致性。(leader会将数据同步给从节点)
性能上比redis差很多,但是可靠性比redis好。
参考目录:
https://blog.csdn.net/weixin_37817685/article/details/89071055 [内存模型]
https://blog.csdn.net/chen77716/article/details/6618779 [synchronize]
https://blog.csdn.net/chen77716/article/details/6641477 [lock]
https://blog.csdn.net/huyaowei789/article/details/87873977 [分布式锁]
原文:https://www.cnblogs.com/ElliottX4/p/14100476.html