文章内容参考了:Java并发编程的艺术、JAVA并发编程之美、深入理解Java虚拟机
> 其实就是抄书。。。
基础知识
为什么要进行并发编程?
很多时候需要多个线程同时执行,但是单核在进行多线程运行的时候,只是让多个线程之间来回的切换执行,并不是并发执行。多核CPU时代 打破了单核CPU对多线程效能的限制。多个CPU意味着每个线程可以使用自己的CPU运行,这减少了线程上下文切换的开销,释放性能。总的来说就是为了程序更快,更充分利用多核资源。
补充:线程是最小的执行单元,进程是最小的资源管理单元。
上下文切换
什么是上下文切换?
单核处理器也只是多线程执行代码,CPU通过给每个线程分配CPU时间片来实现。时间片是分配给每个线程的时间,因为时间片非常短,CPU需要不断的切换线程执行,所以我们感觉是多个线程在同时执行,时间片一般是几十毫秒。
CPU通过时间片分配来执行任务,当上一个任务的时间片结束后就会切换到下一个任务(线程),但是上一个任务并没有执行完,所以会保存上一个任务的状态,以便下一次切换的时候能继续运行(再加载这个任务的状态),`所以任务从保存到再加载的过程就是一次上下文切换。`
多线程一定比单线程快?
不一定,如果是单核的话,多线程最终也是串行执行,一个CPU同时只能执行一个时间片,多线程也只是频繁的切换上下文而已。所以会比单线程慢,毕竟上下文切换也是有损耗的。
多核CPU的话,如果大量数量且逻辑复杂,并发比串行更快。如果任务简单数据量小,会比串行慢,因为有`线程创建和上下文切换的开销`。
参考资料:http://iamzhongyong.iteye.com/blog/1895728
测量上下文切换
具体参考并发编程艺术1.1.2
如何减少上下文切换
- 无锁并发编程。多线程竞争锁时,会引起上下文切花,所以多线程处理数据时,尽量避免使用锁,比如将数据ID按照Hsh算法取模分段,不同的线程处理不同段的数据。
- CAS算法,JAVA的Atomic包使用CAS算法来更新数据,而不需要加锁。
- 使用最少线程,避免不必要的线程创建。
- 协程:在单线程里实现多任务调度,并在多线程里维持多个任务间的切换。
线程安全问题
什么实现线程安全?
线程安全本质是多个线程对共享资源进行操作,而且操作资源的代码有多句。cpu执行多线程时,在执行的过程中可能随时切换到其他的线程上执行。这样造成了运行结果和预期正常结果不一致,准确说是如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
多个线程同时读写一个共享资源并且没有任何同步措施时,导致出现脏读或者其他不可预见结果的问题。
其实就是 每个线程在处理数据时,每次都是从主内存读取数据到线程内存,然后处理完毕之后在写会主内存