互斥锁,自旋锁,原子 *** 作原理和实现

互斥锁,自旋锁,原子 *** 作原理和实现,第1张

注意:互斥锁在上锁的过程中,需要用自旋锁保证原子 *** 作(包括修改原子量和锁的相关数据结构)

自旋锁是采用忙等的状态获取锁,所以会一直占用cpu资源,但是允许不关闭中断的情况下,是可以被其他内核执行路径抢占的(中断嵌套的情况下,注意嵌套的中断不能申请同一个锁,这样会造成死等)。同时因为线程对cpu一直保持占用状态,所以对小资源加锁效率比较高,不需要做任何的线程切换,一般情况下如果加锁资源的运行延迟小于线程或者进程切换的时延则推荐使用自旋锁。如果需要等待耗时 *** 作,则建议放弃cpu,采用信号量或者互斥锁

上图指令可以实现加 *** 作的原子性,但是这种总线锁不能滥用,在没有共享同步问题的时候,这会阻止cpu并行计算的优化,甚至会阻塞cpu对其他内存的访问,导致效率的下降。所以除此之外我们可以使用缓存锁来执行复杂的原子 *** 作。

频繁使用的内存会缓存在处理器的L1、L2和L3高速缓存里,那么原子 *** 作就可以直接在处理器内部缓存中进行,并不需要声明总线锁,在Pentium 6和目前的处理器中可以使用“缓存锁定”的方式来实现复杂的原子性。 所谓“缓存锁定”是指内存区域如果被缓存在处理器的缓存行中,并且在Lock *** 作期间被锁定,那么当它执行锁 *** 作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改内部的内存地址,并允许它的缓存一致性机制来保证 *** 作的原子性,因为缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使缓存行无效,在如图2-3所示的例子中,当CPU1修改缓存行中的i时使用了缓存锁定,那么CPU2就不能同时缓存i的缓存行。

但是有两种情况下处理器不会使用缓存锁定。

未完待续。。。。

>

在并发编程中,synchronized锁因其使用简单,在线程间同步被广泛应用。下面对其原理及锁升级过程进行探究。

当实例方法被synchronized修饰时,通过当前实例调用此方法的所有线程共用一把锁,不同对象调用此方法线程间互不影响。

当使用synchronized锁修饰实例方法,锁添加在当前类的实例上,有多少个实例可添加多少把锁。

修饰代码块比修饰方法颗粒度更小。当实例方法代码块被synchronized修饰时,通过当前实例调用此方法的所有线程共用一把锁,不同对象调用此方法线程间互不影响。

当使用synchronized锁修饰代码块,锁添加在当前类的实例上,有多少个实例可添加多少把锁。

当静态方法被synchronized修饰时,整个JVM所有调用此方法的线程均受同一个锁的约束。

当使用synchronized锁修饰静态方法,锁添加在当前类的类对象上,最多添加一把锁。

Java 8所使用的synchronized锁是经过优化后的,存在偏向锁、轻量级锁、重量级锁等状态。

线程间不存在锁的竞争行为,至多只有一个线程有获取锁的需求,常见场景为单线程程序。

判断是不是偏向锁的标识是查看调用此方法的线程是否有且仅有一个。

在多线程编程里,被锁修饰的方法仅被单一线程调用几乎不存在,因此偏向锁比较鸡肋:如果能够明确单一线程调用目标方法,使用无锁编程更为合适。

无锁与偏向锁的性能差异非常接近,几乎可以忽略不计。

线程间存在锁的伪竞争行为,即同一时刻绝对不会存在两个线程申请获取锁,各线程尽管都有使用锁的需求,但是是交替使用锁。

当有两个及以上线程调用被锁修饰的方法时,那么至少能确定是轻量级锁。

轻量级锁由于同一时刻不存在两个线程互相竞争锁,因此不存在线程阻塞-唤醒的上下文切换,因此性能相对重量级锁要高很多。

线程间存在锁的实质性竞争行为,线程间都有获取锁的需求,但是时间不可交错,互斥锁的阻塞等待。

当能够肯定至少有两个及以上线程调用被锁修饰的方法时,线程调用方法是随机的,那么大概率是重量级锁。

重量级锁由于涉及到线程阻塞-唤醒的上下文切换,造成相比较与无锁状态,效率低很多。

synchronized锁是非公平锁,没有FIFO队列机制保障竞争锁的线程一定有几率获得锁。

synchronized锁是可重入锁,可重入意味着嵌套调用不会产生死锁问题。

synchronized锁是一种悲观锁,通过加锁实现线程间同步。

在多线程环境下,如果使用synchronized锁,那么大概率会升级到重量级锁。偏向锁和轻量级锁非刻意为之,很难存在,更大的意义是对比帮助理解重量级锁的性能。

重量级锁尽管会对性能产生很大影响,但是依旧是解决线程间同步的有效手段。

当被锁修饰的方法或者代码块执行时间较长时,选用基于线程阻塞-唤醒切换上下文的方式进行线程同步效率相对较高。

当被锁修饰的方法或者代码块执行时间较短时,应选用其它替代锁,比如自旋锁等。

在实际多线程场景开发中,synchronized锁大概率会升级到重量级锁,因其单向升级的特点,重量级状态的synchronized锁可能会对实际业务的并发产生不利影响,手动选用其它锁可能会更合适。

synchronized锁仅可用于解决同一进程内不同线程间同步,对于分布式项目跨进城线程同步依赖于分布式锁,synchronized锁更多的意义是理解锁的过程。

挂号时没有提前缴纳费用。锁号中的意思就是账号在被锁的过程中,密码输错很多次就会锁号、又或者是医院挂的号被锁号等等,获取锁号号源失败是挂号时没有提前缴纳费用,是因为你用医保进行挂号的时候没有提前缴纳费用。

以上就是关于互斥锁,自旋锁,原子 *** 作原理和实现全部的内容,包括:互斥锁,自旋锁,原子 *** 作原理和实现、synchronized的锁升级过程、多线程高并发之Synchronized锁及其膨胀等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/web/9753979.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存