--- 写该系列旨在记录自己的学习,“理解不深”,慢慢补充。
学习并发编程的目的:
1.最直接的回答:面试需要。
2.哈哈哈哈,以后肯定会用到的。
进入正题
首先学习前了解两个概念:
并发:多个线程在同一时间间隔,一起运行的状态。
并行:多个线程在同一时刻,一起运行的状态。
一:并发存在的目的意义:
并发编程是为了让程序运行的更快,相比但单线程,使用多个线程处理一项任务,明显具有优越性。但在使用多线程时要注意,比如进程之间的通信和同步问题。
多线程一定比单线程块吗?
语言描述一下:创建10个线程去执行对一个全局变量i 的+10操作,每次++i;与用main一个线程去 j 自加到100,哪个会先执行完呢。下图为书中的图,在不同的数量下 使用多线程并发的方式和 使用单线程的方式对比,在大数量下多线程会有优势。
二:为什么会导致这种情况呢?因为多线程使用时会有 线程的创建,及上下文的切换开销的问题。
(上下文切换,cpu会进行时间的轮转,当此次的时间片耗尽之前,进程要记录当的执行位置及状态,(突然想起操作系统老师说的通过栈的方式 ,压入到栈中记录)当下次时间片轮转到来时,需要将记录的这些信息弹栈,继续执行)
(上下文切换 (context switch) , 其实际含义是任务切换, 或者CPU寄存器切换。当多任务内核决定运行另外的任务时, 它保存正在运行任务的当前状态, 也就是CPU寄存器中的全部内容。这些内容被保存在任务自己的堆栈中, 入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装入CPU寄存器, 并开始下一个任务的运行, 这一过程就是context switch)
那应该如何解决呢?
三:如何减少上下文的切换
切换上下文方法有:
- 无并发编程:上下文切换 是因为在多个线程在竞争锁时才会出现,给多个线程进行分配任务,让不同的线程去处理不同的任务,互不干扰(书中的解释:将数据ID按照Hash算法 取模运算 分段,不同线程处理不同段的数据),比如 多线程去下载一个文件如 IDM下载器中,分段下载,然后合并一个文件。
- CAS算法 : 多线程 不使用锁,也可以使用CAS JAVA Atomic包中的类来对不同数据类型保证线程安全 ,类如AtomicInterger ,AtomicString AtomicStampInterger (带有标记版本的CAS 解决常规的CAS 出现的ABA问题,后面会写到)。
- 使用最少的线程去完成任务。
- 协程 :在单线程中实现多任务的调度,并在单线程中维持多任务的切换。
四:减少上下文切换的配置方法的解决办法:
- 第一步:用jstack命令dump线程信息,看看pid为3117的进程里的线程都在做什么。
- 第二步:统计所有线程分别处于什么状态,发现300多个线程处于WAITING(onobjectmonitor)状态。
- 第三步:打开dump文件查看处于WAITING(onobjectmonitor)的线程在做什么。发现这些线 程基本全是JBOSS的工作线程,在await。说明JBOSS线程池里线程接收到的任务太少,大量线程都闲着。
- 第四步:减少JBOSS的工作线程数,找到JBOSS的线程池配置信息,将将maxThreads降到 100。
- 第五步:重启JBOSS,再dump线程信息,然后统计WAITING(onobjectmonitor)的线程,发现 减少了175个。WAITING的线程少了,系统上下文切换的次数就会少,因为每一次从 WAITTING到RUNNABLE都会进行一次上下文的切换。读者也可以使用vmstat命令测试一下。
补什么是jboss https://blog.csdn.net/iiiiher/article/details/70158290?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
未完待写