第一章 并发编程的挑战
2021/5/13 20:55:23
本文主要是介绍第一章 并发编程的挑战,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
第1章 并发编程挑战
并发编程的目的是为了使程序运行更快,但是,并不意味着启动更多线程就可让程序最大限度并发执行
1.1 上下文切换
CPU为不同线程分配不同的时间块来支持多线程执行代码(类似于时分复用),但是在切换到下一个任务之前,会将现在这个任务状态保存,以便下次可以再加载这个任务状态。任务从保存到再加载的过程就称为依次上下文切换
package com.chapter1; import static java.lang.System.currentTimeMillis; public class ConcurrentTest { private static long count = 100000000; public static void main(String[] args) throws InterruptedException { concurrency(); serial(); } //并发计算结果 private static void concurrency() throws InterruptedException { long start = currentTimeMillis(); //开启一个线程计算结果 Thread thread = new Thread(()->{ long sum = 0; for (int i = 0; i < count; i++) { sum = sum + 5; } }); thread.start(); //主线程循环减 int b = 0; for (int i = 0; i < count; i++) { b--; } //插队 thread.join(); long time = System.currentTimeMillis() - start; System.out.println("concurrency:" + time); } //普通单线程计算 private static void serial() { long start = System.currentTimeMillis(); long sum = 0; for (int i = 0; i < count; i++) { sum = sum + 5; } int b = 0; for (int i = 0; i < count; i++) { b--; } long time = System.currentTimeMillis() - start; System.out.println("serial:" + time); } }
通过例子发现,随着count的值增加,多线程优势逐渐显现出来,在count较小时,所用时间大于单线程时间。经过分析发现,这是因为上下文切换带来的时间损耗。
1.2 减少上下文切换
减少上下文切换方法有:无锁并发编程,CAS算法,使用最少线程和使用协程
- 无锁并发编程:多个线程竞争锁时,会引发上下文切换,因此使用一些方法来避免使用锁
- CAS算法:Java的Atomic包使用CAS算法更新数据,不需要加锁
- 使用最少线程:即尽量少使用线程,避免创建过多不需要的线程
- 协程:在单线程中实现多任务的调度
1.3 死锁
死锁产生的四个必要条件:
- 互斥条件:一个资源被一个进程占用
- 请求与保持条件:一个资源请求对方资源陷入等待,另一个线程不释放资源
- 不剥夺条件:进程获得的资源在未释放之前不可被强行剥夺
- 循环等待条件:若干进程间形成循环等待关系
package com.chapter1; import java.util.concurrent.TimeUnit; public class DeadLockTest { //两个资源 private static String A = "A"; private static String B = "B"; public static void main(String[] args) { deadlock(); } private static void deadlock() { //开启t1线程 new Thread(()->{ synchronized (A) { System.out.println(Thread.currentThread().getName() + "get A"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (B) { System.out.println(Thread.currentThread().getName() + "get B"); } } }, "t1").start(); //开启t2线程 new Thread(()->{ synchronized (B) { System.out.println(Thread.currentThread().getName() + "get B"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (A) { System.out.println(Thread.currentThread().getName() + "get A"); } } }, "t2").start(); } }
避免死锁的几个常用方法:
- 避免一个线程获得多个锁
- 避免一个线程在锁内占用多个资源,尽量保证每个锁仅占用一个资源
- 使用定时锁(lock.tryLock(timeout))来代替内部锁
- 对于数据库锁,加锁和解锁必须在同一个数据库连接中
1.4 资源限制问题
什么是资源限制
资源限制是指在并发编程中,程序执行速度受限于计算机硬件资源或软件资源
资源限制引发的问题
并发编程的原则是将代码中串行执行的部分编程并发执行。但由于资源限制问题,本质上还是串行,同时由于上下文切换和资源调度问题,时间反而会增加。
如何解决资源限制问题
硬件资源限制:使用集群并行执行程序。让程序在多个计算机上执行,比如使用ODPS,Hadoop搭建服务器集群
软件资源限制:使用资源池将资源复用。
资源限制下的并发编程
在资源限制下,根据不同的资源限制调整程序的并发度。
这篇关于第一章 并发编程的挑战的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求
- 2024-10-01使用 golang 将ETH账户的资产平均分散到其他账户
- 2024-10-01JWT用户校验课程:从入门到实践
- 2024-10-01Server Component课程入门指南
- 2024-09-30Dnd-Kit学习:新手快速入门指南