读《JAVA并发编程的艺术》笔记---第一步,分析多线程与单线程的区别,以及并发带来的问题和解决方法

本文探讨了多线程并发编程中的上下文切换问题,并通过实验对比了单线程与多线程处理同一任务的效率差异。文章还介绍了几种减少上下文切换以提高程序执行效率的方法。

前言:由于工作上用户量逐渐增加,慢慢的牵扯到了一些下单并发问题,在没有特别处理之前,着实绕了很大一圈才解决,为了加强自己的并发经验,所以花了血本狠心买了一本JAVA并发编程的艺术,在学习的同时,准备做一些笔记记录,以备后用.

并发编程,是为了让程序可以更快且安全的运行,以之前的想法,以为开启更多的线程处理同一业务,就可以让程序更快的处理完成,没有考虑到一些开启多线程带来的问题;

然后博主了解到一些常见的并发问题:1.多线程上下文切换,2.死锁,3.多线程资源竞争等

1.关于多线程上下文切换

开启多线程时,CPU会给每个线程分配CPU时间片,因为分配给各个线程的时间片很短,所以CPU通过不停的切换线程执行,给人一种多个线程同步执行的感觉效果,这个时间片一般为几十毫秒(ms)。

CPU通过时间片分配算法循环执行任务(线程),当前线程执行到一个时间片单位之后,会切换到下一个线程执行,同时保存当前线程执行状态,便于切换回当前线程,这个线程保存和切换的过程就是一次上下文切换;书中举了一个很通俗的例子:就像博主看Spring API 英文版时,发现某个单词不认识,只得翻看英语词典,但在我查看英语词典之前,还要先记录api的位置,查看之后再回到api才能继续往下读,这样一个过程影响了博主看API的效率;同样,上下文切换也一样影响了多线程的总体运行时间。

博主通过以下一段简单的代码测试,用以证实了多线程存在上下文切换;

private static final long count = 100000000l;//private static final long count = 10000l;

//多/单线程执行1E/1W的+-操作

long start = System.currentTimeMillis();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
for (int j = 0; j < count; j++) {
i+=5;
}
}
});
thread.start();
int b = 0;
for (int i = 0; i < count; i++) {
b--;
}
thread.join();
long time = System.currentTimeMillis() - start;
System.err.println(count + "次执行时间--多线程并行:" + time + "ms");

long start = System.currentTimeMillis();
int a = 0;
for (int j = 0; j < count; j++) {
a+=5;
}
int b = 0;
for (int i = 0; i < count; i++) {
b--;
}
long time = System.currentTimeMillis() - start;
System.err.println(count + "次执行时间--单线程串行:" + time + "ms
");

测试结果:

当数据为10000时,单线程处理时间为:0ms(忽略不计),多线程为:1ms;---耗费多出一倍的处理时间

当数据为100000000时,单线程处理时间为:104ms,多线程为:54ms; ---节省了约一倍的处理时间

结论

多线程确切存在上下文切换,所以不是所有场景都适用多线程处理.具体如果实现应以业务为依据

引申思考,如何减少上下文切换

按照书上所述,减少上下文切换的方法有:无锁并发编程,CAS算法,用最少的线程和协程。

-无锁并发编程,多线程竞争锁时,就会引起频繁的上下文切换,可以尽量不加锁来避免上下文切换,如将业务数据ID按照规则(如hash取模),各自线程处理属于各自的数据

-CAS算法,Java自带的Atomic包使用了CAS算法来操作数据变量,同样不需要加锁,具体往后再发专题博客

-使用最少线程或协程,减少不必要的线程开销,将任务分配到合理的线程量,协程则是在单线程环境里实现多任务调度和任务切换。(关于协程博主也暂时还没了解到,后续更新)

由于是在工作中挤出时间来学习研究,具体内容下一篇继续,先分析线程运行状态,再针对性减少线程,减少上下文切换开销

下篇内容:读《JAVA并发编程的艺术》笔记---第二步,使用jstack查找分析程序运行时线程状态

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值