关于并发编程,其目的就是为了让程序运行得更快,可是,并非启动更多的线程就能让程序更大限度的并发执行。有哪些影响并发编程的因素呢?java
单核处理器也支持多线程执行代码,CPU经过给每一个线程分配CPU时间片来实现这个机制,只是时间片的时间短,感受CPU能同时处理多个任务。时间片通常是几十毫秒(ms)。
CPU经过时间片轮训的方式处理任务,当前任务执行一个时间片会切换到下一个任务。注意,当CPU从一个任务切换到另外一个任务前,会保留上一个任务的状态,以便再切回来是能够继续执行。因此任务从保持状态到再加载的过程就是一次上下文切换。算法
电脑配置:单处理器双核8G内存
public class Demo1_1_1 { private static final long count = 1000000001; public static void main(String[] args) throws InterruptedException { // 注释一个进行执行 concurrent(); // serial(); } /** * 并发执行 */ private static void concurrent() throws InterruptedException { long start = System.currentTimeMillis(); Thread thread = new Thread(() -> { int a = 0; for (long i = 0; i < count; i++) { a += 5; } }); thread.start(); int b = 0; for (long i = 0; i < count; i++) { b --; } thread.join(); System.out.println("concurrent time:" + (System.currentTimeMillis() - start) + "ms"); } /** * 串行执行 */ private static void serial() { long start = System.currentTimeMillis(); int a = 0; for (long i = 0; i < count; i++) { a += 5; } int b = 0; for (long i = 0; i < count; i++) { b --; } System.out.println("serial time:" + (System.currentTimeMillis() - start) + "ms"); } }
以上分别执行3次,取一个最大值和一个最小值
结果数据库
循环次数 | 并行耗时/ms | 串行耗时/ms |
---|---|---|
10万 | 66 - 90 | 2 - 4 |
100万 | 68 - 78 | 5 - 13 |
1000万 | 75 - 81 | 16 - 19 |
1亿 | 133 - 128 | 80 - 121 |
10亿 | 600 - 615 | 900 - 1000 |
分析
当并发执行不超过亿级别时,并行是比串行慢的,这就是由于线程有建立和上下文切换的开销。按理说多个线程执行应该比单线程慢,实际并不是如此。编程
一、无所并发编程:多线程竞争锁时,会引起上下文切换
二、CAS算法:Java中的Atomic包使用CAS算法更新数据,无需加锁
三、使用最少线程:任务少,但线程多,致使不少线程都处于等待状态
四、协程:在线程里实现多线程的调度多线程
java中的锁主要用来解决并发编程资源竞争的问题,若是编程不当,一旦产生死锁,便会致使系统功能不可用。并发
例如,有两个线程t1,t2;两个资源A,B;当出现,t1持有A资源,t2持有B资源时,t1尝试获取B资源,t2尝试获取A资源,此时,便会出现死锁的状况。
一、避免一个线程同时获取多个锁
二、避免一个线程在锁内同时占有多个资源,尽力保证每一个线程只占用一个资源
三、尝试使用定时锁,如lock.tryLock(timeout)测试
资源限制指在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。
硬件资源包括:带宽的上传下载速度、硬盘读写速度和CPU的处理速度等
软件资源包括:线程池大小、数据库的链接数等spa
在并发编程中,代码执行速度加快的原则是将代码中的串行部分变成并行执行,但有可能因为资源限制问题,致使程序仍按串行执行,此时程序不只不会变快,反而更慢,由于增长了上下文切换和资源调度的时间。线程
对于硬件资源限制:考虑使用集群方式并行执行程序。
对于软件资源限制:考虑使用资源池将资源复用,例如数据库链接池等code
根据不一样的资源限制调整程序的并发度。