李林LiLin
Java多线程问题汇总
原创
关注作者
前往小程序,Get
更优
阅读体验!
立即前往
腾讯云
开发者社区
文档
建议反馈
控制台
登录/注册
首页
学习
活动
专区
工具
TVP
最新优惠活动
文章/答案/技术大牛
搜索
搜索
关闭
发布
首页
学习
活动
专区
工具
TVP
最新优惠活动
返回腾讯云官网
李林LiLin
首页
学习
活动
专区
工具
TVP
最新优惠活动
返回腾讯云官网
社区首页
>
专栏
>
Java多线程问题汇总
Java多线程问题汇总
原创
李林LiLin
关注
修改于 2023-04-01 16:39:14
353
0
修改于 2023-04-01 16:39:14
举报
文章被收录于专栏:
Android进阶编程
1、线程中start()、run(),wait()、sleep(),sleep() 、join()、yield()有什么区别?
1.1、线程中start和run方法有什么区别
调用start()方法时会执行run()方法,不能直接调用run()方法
。调用start()方法时将创建新的线程,并且执行在run()方法里的代码。但是直接调用run()方法,不会创建新的线程也不会执行调用线程的代码。
1.2、wait和sleep方法的不同
让当前执行线程陷入等待(注意:不一定是调用wait方法的线程,也就是执行这行代码的线程),在等待时wait会释放锁,而sleep一直持有锁
。Wait通常被用于线程间交互,sleep通常被用于暂停执行。
1.3、sleep()方法
在指定的毫秒数内让当前正在执行的线程休眠(暂停执行
),此操作受到系统计时器和调度程序精度和准确性的影响。 让其他线程有机会继续执行,
但它并不释放对象锁
。也就是如果有Synchronized同步块,其他线程仍然不能访问共享数据。注意该方法要捕获异常。
比如有两个线程同时执行(没有Synchronized),一个线程优先级为MAX_PRIORITY,另一个为MIN_PRIORITY,如果没有Sleep()方法,只有高优先级的线程执行完成后,低优先级的线程才能执行;但当高优先级的线程sleep(5000)后,低优先级就有机会执行了。sleep()可以使低优先级的线程得到执行的机会,当然也可以让同优先级、高优先级的线程有执行的机会。
1.4、yield()方法
yield()方法和sleep()方法类似,它没有参数,
也不会释放“锁标志”
,
只是提出申请释放CPU资源,至于能否成功释放由JVM决定。
即yield()方法只是使当前线程重新回到可执行状态(
RUNNABLE
),所以执行yield()的线程有可能在进入到可执行状态后马上又被执行,另外
yield()方法只能使同优先级或者高优先级的线程得到执行机会
,这也和sleep()方法不同。
1.5、join()方法
t.join()的意思是阻塞当前线程(即执行t.join()这条语句的线程),直到线程t完成,此线程再继续。
join之所以可以实现线程等待是因为调用wait方法。
Thread的join()有什么作用?
1.6、Thread.sleep(0)的作用是啥?
由于Java采用抢占式的线程调度算法,因此可能会出现某条线程常常获取到CPU控制权的情况,为了让某些优先级比较低的线程也能获取到CPU控制权,可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作,这也是平衡CPU控制权的一种操作。
2、ReentrantLock和synchronized的区别
2.1、保障线程安全有哪些手段,可从多线程三特性出发:
原子性(Atomicity):单个或多个操作是要么全部执行,要么都不执行
Lock:保证同时只有一个线程能拿到锁,并执行申请锁和释放锁的代码
synchronized:对线程加独占锁,被它修饰的类/方法/变量只允许一个线程访问
可见性(Visibility):当一个线程修改了共享变量的值,其他线程能够立即得知这个修改
volatile:保证新值能立即同步到主内存,且每次使用前立即从主内存刷新;
synchronized:在释放锁之前会将工作内存新值更新到主存中
有序性(Ordering):程序代码按照指令顺序执行
volatile: 本身就包含了禁止指令重排序的语义
synchronized:保证一个变量在同一个时刻只允许一条线程对其进行lock操作,使得持有同一个锁的两个同步块只能串行地进入
2.2、ReentrantLock和synchronized的区别
ReentrantLock:
等待可中断:当持有锁的线程长期不释放锁的时候,正在等待的线程可以选择放弃等待,改为处理其他事情。
公平锁:多个线程在等待同一个锁时,必须按照申请锁的时间顺序来依次获得锁。而
synchronized是非公平的
,即在锁被释放时,任何一个等待锁的线程都有机会获得锁。
ReentrantLock默认情况下也是非公平的,但可以通过带布尔值的构造函数改用公平锁
。
锁绑定多个条件
:一个ReentrantLock对象可以通过多次调用newCondition()同时绑定多个Condition对象。而在synchronized中,锁对象wait()和notify()或notifyAl()只能实现一个隐含的条件,若要和多于一个的条件关联不得不额外地添加一个锁。
Synchronized:
是悲观锁机制,独占锁
。而Locks.ReentrantLock是每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。
2.3、ReentrantLock适用场景
某个线程在等待一个锁的控制权的这段时间需要中断
需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程,锁可以绑定多个条件。
具有公平锁功能,每个到来的线程都将排队等候。
3、Volatile和Synchronized的区别
3.1、Volatile和Synchronized各自用途是什么?有哪些不同点?
粒度不同,前者针对变量 ,后者锁对象和类。
Synchronized阻塞,volatile线程不阻塞。
Synchronized保证三大特性(原子性、可见性、有序性),volatile不保证原子性
Synchronized编译器优化,volatile不优化,volatile具备两种特性:
保证此变量对所有线程的可见性,指一条线程修改了这个变量的值,新值对于其他线程来说是可见的,但并不是多线程安全的。
禁止指令重排序优化。
Volatile如何保证内存可见性:
当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存。
当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。
3.2、Synchronize在编译时如何实现锁机制?
Synchronized经过编译,会
在同步块的前后分别形成monitorenter和monitorexit这个两个字节码指令
。在执行monitorenter指令时,首先要尝试获取对象锁。如果这个对象没被锁定,或者当前线程已经拥有了那个对象锁,把锁的计算器加1,相应的,在执行monitorexit指令时会将锁计算器就减1,当计算器为0时,锁就被释放了。如果获取对象锁失败,那当前线程就要阻塞,直到对象锁被另一个线程释放为止。
3.3、用volatile修饰,多线程去操作++,线程安全吗?那如何才能保证i++线程安全?
不安全
volatile只能保证可见性,并不能保证原子性
。
i++实际上会被分成多步完成:
获取i的值;
执行i+1;
将结果赋值给i。
volatile只能保证这3步不被重排序
,多线程情况下,可能两个线程同时获取i,执行i+1,然后都赋值结果2,实际上应该进行两次+1操作。
如何才能保证i++线程安全
可以使用java.util.concurrent.atomic包下的原子类,如AtomicInteger。其实现原理是采用CAS自旋操作更新值。
4、CAS原理
4.1、CAS原理是什么
CAS即compare and swap的缩写,中文翻译成比较并交换。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。自旋就是不断尝试CAS操作直到成功为止。
4.2、CAS实现原子操作会出现什么问题
ABA问题。因为CAS需要在操作之的时候,检查值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成,有变成A,那么使用CAS进行检查时会发现它的值没有发生变化,但实际上发生了变化。ABA问题可以通过添加版本号来解决。Java 1.5开始,JDK的Atomic包里提供了一个类AtomicStampedReference来解决ABA问题。
循环时间长开销大。pause指令优化。
只能保证一个共享变量的原子操作。可以合并成一个对象进行CAS操作。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
java
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系
cloudcommunity@tencent.com
删除。
java
评论
登录
后参与评论
0 条评论
热度
最新
推荐阅读
LV.
文章
0
获赞
0
目录
1、线程中start()、run(),wait()、sleep(),sleep() 、join()、yield()有什么区别?
1.1、线程中start和run方法有什么区别
1.2、wait和sleep方法的不同
1.3、sleep()方法
1.4、yield()方法
1.5、join()方法
1.6、Thread.sleep(0)的作用是啥?
2、ReentrantLock和synchronized的区别
2.1、保障线程安全有哪些手段,可从多线程三特性出发:
2.2、ReentrantLock和synchronized的区别
2.3、ReentrantLock适用场景
3、Volatile和Synchronized的区别
3.1、Volatile和Synchronized各自用途是什么?有哪些不同点?
3.2、Synchronize在编译时如何实现锁机制?
3.3、用volatile修饰,多线程去操作++,线程安全吗?那如何才能保证i++线程安全?
4、CAS原理
4.1、CAS原理是什么
4.2、CAS实现原子操作会出现什么问题
领券
问题归档
专栏文章
快讯文章归档
关键词归档
开发者手册归档
开发者手册 Section 归档
0
0
0
推荐