Java性能优化-05-线程上下文切换

文章介绍了线程上下文切换的概念,包括时间片轮转和状态转换,并指出跨CPU核心的切换更为昂贵。上下文切换分为自发性和非自发性两种,前者由程序调用如sleep()、wait()等引发,后者由调度器或系统因素导致。为了优化,文章提出减少锁持有时间、降低锁力度、使用非阻塞乐观锁、优化wait/notify机制以及合理设置线程池大小等策略。

1-线程上下文切换介绍

CPU 时间片是 CPU 分配给每个线程执行的时间段,一般为几十毫秒。时间片决定了一个线程可以连续占用处理器运行的时长。当一个线程的时间片用完了,或者因自身原因被迫暂停运行了,这个时候,另外一个线程(可以是同一个线程或者其它进程的线程)就会被操作系统选中,来占用处理器。这种一个线程被暂停剥夺使用权,另外一个线程被选中开始或者继续运行的过程就叫做上下文切换(Context Switch)

在当前 CPU 数量远远不止一个的情况下,操作系统将 CPU 轮流分配给线程任务,此时的上下文切换就变得更加频繁了,并且存在跨 CPU 上下文切换,比起单核上下文切换,跨核切换更加昂贵。

一个线程的状态由 RUNNING 转为 BLOCKED ,再由 BLOCKED 转为 RUNNABLE ,然后再被调度器选中执行,这就是一个上下文切换的过程。

上下文切换诱因:

  • 一种是程序本身触发的切换,这种我们称为自发性上下文切换,

  • 另一种是由系统或者虚拟机诱发的非自发性上下文切换。

自发性上下文切换指线程由 Java 程序调用导致切出,在多线程编程中,执行调用以下方法或关键字,常常就会引发自发性上下文切换。

sleep(),wait(),yield(),join(),park(),synchronized,lock

非自发性上下文切换指线程由于调度器的原因被迫切出。常见的有:线程被分配的时间片用完,虚拟机垃圾回收导致或者执行优先级的问题导致。

2-优化措施

在多线程编程中,锁其实不是性能开销的根源,竞争锁才是。

  • 减少锁持有时间:没有线程安全的代码块,不用加锁

  • 降低锁力度:比如锁分离(读写锁),分段锁(Java1.8 之前版本的 ConcurrentHashMap 就使用了锁分段)

  • 非阻塞乐观锁替代竞争锁:Java 的 Atomic 包就使用了 CAS 算法来更新数据,就不需要额外加锁。

  • wait/notify优化:建议使用Lock锁结合Condition 接口替代Synchronized内部锁中的 wait / notify,实现等待/通知。

  • 合理地设置线程池大小,避免创建过多线程

  • 减少Java虚拟机的垃圾回收

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值