再探JUC-8锁现象

第二篇Java技术分享(再探JUC-8锁现象)
Jpunster
前文:小伙伴们,大家好,这篇技术分享主要是讲解一下 JUC-locks下存在的8锁的问题(关于锁的8个问题),为了解决面试时不会判断锁的问题:知道是什么锁,并且判断锁的是谁!
在这里插入图片描述

在开始正文之前,我们先来解决上篇文章遗留的一个小作业,i++是否是线程安全的?不知道大家有没有想出来呢?

答案是:是不安全的。

举个例子:

tp = i;
tp2 = i+1;
i=tp2;
如果线程1在执行第一条代码的时候,线程2访问i变量,这个时候,i的值还没有变化,还是原来的值,所以是不安全的。

源码分析:根据JMM理论:线程解锁前,必须把共享变量立刻刷回主存。2、线程加锁前,必须读取主存中的最新值到工作内存中!3、加锁和解锁是同一把锁。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(图为狂神说提供)

所以i++是线程不安全的,那么如何实现线程安全呢
在这里插入图片描述
在这里插入图片描述atomic.AtomicInteger.getAndIncrement这个方法是线程安全的。

面试回答:i++不是线程安全的。在juc包下的atomic.AtomicInteger.getAndIncrement 方法是线程安全的。因为在多线程下,根据JMM 模型,每个线程 有自己独立的运行内存,当它执行i++时,先去主存中load共享变量到自己的工作内存中,运算完成后再save回主存,在save时,有可能被其他线程覆盖掉共享变量的值,所以 i++不是线程安全的。而 getAndIncrement 底层调用了unSafe()方法 是调用C++ 可以直接操作内存,所以AtomicInteger.getAndIncrement方法是线程安全的。

正文:

1.0 多个线程使用同一把锁----顺序执行
在这里插入图片描述
在这里插入图片描述
第一种情况:锁的对象是方法的调用者,两个线程同时争夺同一把锁,是按照顺序来执行的,发短信线程在前,所以发短信先执行。
在这里插入图片描述
Tips:1.不要显式创建线程,要使用线程池来创建线程。2.线程池创建线程时,不要使用Executor来创建线程池(可能造成OOM)要使用ThreadPoolExecutor来创建。(后续会分享线程池知识)
在这里插入图片描述
2.0 多个线程使用同一把锁,其中某个线程里面还有阻塞----顺序先行
在这里插入图片描述
在这里插入图片描述
第二种情况:多个线程使用同一个对象,多个线程就是使用一把锁,先调用的先执行,即使在某方法中设置了阻塞。发短信线程在前,所以发短信先执行。
在这里插入图片描述
3.0 多个线程有锁与没锁(同一把锁)----按照时间执行
在这里插入图片描述
在这里插入图片描述
第三种情况:多个线程(使用同一把锁),有的线程有锁,有的线程(普通方法)没锁,两者之间不存在竞争同一把锁的情况,因为设置打电话延时,所以先执行普通方法(发微信)。
在这里插入图片描述
4.0 多个线程使用多把锁----按照时间执行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第四种情况:被 synchronized 修饰的方法,锁的对象是方法的调用者;
调用者不同,它们之间用的不是同一个锁,相互之间没有关系,互不干扰。
在这里插入图片描述
5.0 Class锁:多个线程使用同一个对象----顺序执行
在这里插入图片描述
在这里插入图片描述
第五种情况:锁Class和锁对象的区别:

1、Class锁,类模版,只有一个;

2、对象锁 , 通过类模板可以new 多个对象。

如果全部都锁了Class(方法同时被synchronized和static修饰),那么这个类下的所有对象都具有同一把锁,执行顺序是顺序执行。
在这里插入图片描述
6.0 Class锁:多个线程使用多个对象----顺序执行
在这里插入图片描述
在这里插入图片描述
第六种情况:两个静态同步方法,两个不同对象,被 synchronized 和 static 修饰的方法,锁的对象是类的 class 对象,是唯一的一把锁。Class锁是唯一的,所以多个对象使用的也是同一个Class锁,所以是顺序执行。
在这里插入图片描述
7.0 Class锁与对象锁:多个线程使用一个对象----按照时间执行
在这里插入图片描述
在这里插入图片描述
第七种情况:1个静态的同步方法,1个普通的同步方法 ,一个对象,被 synchronized和static修饰的方法,锁的对象是类的class对象!唯一的同一把锁;只被synchronized修饰的方法,是普通锁(如对象锁),不是Class锁,所以进程之间执行顺序互不干扰,因为在打电话方法延时4S,所以先执行发短信方法。
在这里插入图片描述
8.0 Class锁与对象锁:多个线程使用多个对象----按照时间执行
在这里插入图片描述
在这里插入图片描述
第八种情况:1个静态的同步方法,1个普通的同步方法 ,两个对象,被 synchronized和static修饰的方法,锁的对象是类的class对象!唯一的同一把锁;只被synchronized修饰的方法,是普通锁(如对象锁),不是Class锁,所以进程之间执行顺序互不干扰,因为在打电话方法延时4S,所以先执行发短信方法。
在这里插入图片描述
小结:1.只有synchronized修饰的方法是普通锁,锁的是调用者。

2.被synchronized 和 static 同时修饰的 方法,锁的是Class类的模板,用的是同一把锁。

至此,8锁问题已经全部说完,有不明白的小伙伴可以多看两遍,也可以私信作者,源码微信公众号:Jpunster 后台回复: 8锁 即可获得(或者扫码关注),留下一个小疑问:如何在面试时很简单的写一个死锁,下期我们提供一个百试不爽的死锁案例~

下篇我们将介绍各种锁的使用情况,以及在分布式下实战时使用较为广泛的锁~
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值