并发编程的挑战

并发编程中,我们或多或少会遇到线程上下文切换、死锁、受限于软硬件资源限制的挑战。

上下文切换

CPU会通过时间片分配算法给各个线程分配时间片来实现多线程机制。获得CPU时间片的线程将可以执行。当前一个线程执行一个时间片后会切换到下一个线程,线程切换前需要保存执行的状态,下回该线程切换回来时再加载这个执行状态,线程状态从保存到再加载的过程就是一次上下文切换。线程上下文切换会消耗一定的资源,如何减少上下文切换呢?

减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。

  • 无锁并发编程
    多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些方法来避免使用锁,如将数据的ID按照Hash算法取模分段,不同的线程处理不同段的数据。

  • CAS算法
    Java的Atomic包使用CAS算法来更新数据,而不需要加锁。

  • 使用最少线程
    避免创建不需要的线程,不如任务很少,但是创建了很多线程来处理,这样会造成大量线程处于等待状态。

  • 协程
    在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换。

死锁

锁是个非常有用的工具,运用场景多、使用简单、易于理解。但如果产生死锁,就会造成系统功能不可用。那么如何避免死锁?

避免死锁的常见几个方法如下

  • 避免一个线程同时获取多个锁。
  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。
  • 尝试使用定时锁,使用Lock.tryLock( timeout )来替代使用内部锁机制。
  • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

软硬件资源限制

在并发编程中,将代码执行速度加快的原则是将代码中串行执行的部分变成并发执行,如果因为受限于资源限制,仍在串行,因为增加了上下文切换和资源调度的时间,这时候程序不仅不会加快执行,反而会变慢。例如服务器带宽为2Mb/s,某个资源的下载速度是1Mb/s,系统启动10个线程下载资源,下载速度不会变成10Mb/s。如何解决资源限制的问题?

  • 硬件资源限制
    可以考虑使用集群并行执行程序。可以通过“数据ID%机器数”,计算得到一个机器编号,然后由对应编号的机器处理这部分数据。

  • 软件资源限制
    可以考虑使用资源池将资源复用,比如使用连接池将数据库和Socket连接复用,或者在调用第三方WebService接口获取数据时,只建立一个连接。

  • 调整并发度
    根据不同的资源限制调整程序的并发度,可以让程序执行的更快。如,有数据库操作时,设计数据库连接数,如果SQL执行非常快,而线程的数量比数据库连接数大很多,则某些线程会被阻塞,等待数据库连接。

J.U.C

我们在并发编程中难免遇到问题,有的程序写的不严谨,在并发下如果出现问题,定位起来会比较耗时和棘手。对应Java工程师来说,幸运的是JDK并发包(java.util.concurrent监测J.U.C)为我们提供了不少经过充分测试和优化的并发容器和工具,能够帮助我们更好的解决并发问题。

J.U.C整体框架

  • Atomic
    该包下主要是一些原子变量类,仅依赖于Unsafe,并且被其他模块所依赖,同时在实际编程中应用较普遍,所以需要先研究该包。重点理解AtomicBoolean、AtomicInteger、AtomicLong的原理(底层逻辑较简单,直接调用Unsafe操作实现),有精力可以看看原子数组的实现,其他的类可暂时不看,在实际应用及码源中几乎很少用到。

  • Locks
    该包下主要是关于锁及其相关类,仅依赖于Unsafe或内部依赖,并且被其他高级模块所依赖。由于LockSupport类底层逻辑简单且仅依赖Unsafe,同时为其他高级模块所依赖,所以需要先了解LockSupport类的运行原理,然后重点研究AbstractQueuedSynchronizer框架,理解独占锁和共享锁的实现原理,并清楚Condition如何与AbstractQueuedSynchronizer进行协作,最后很容易就能理解ReentrantLock是如何实现的。

  • Collections
    该包会依赖Unsafe和前两个基础模块,并且模块内部各个容器间相互较为独立,所以没有固定的学习顺序,理解编程中常用的集合类原理即可:ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet、ArrayBlockingQueue、LinkedBlockingQueue(阻塞队列在线程池中有使用,所以理解常用阻塞队列的特性很重要)

  • Executor
    这一部分的核心是线程池的运行原理,也是实际应用中较多的部分,会依赖于前几个模块。首先了解Callable、Future、RunnableFuture三个接口间的关系以及FutureTask的实现原理,然后研究如何创建ThreadPoolExecutor,如何运行一个任务,如何管理自身的线程,同时了解RejectedExecutionHandler的四种实现差异,最后,在实际应用中学习如何通过调整ThreadPoolExecutor的参数来优化线程池。

  • Tools
    这一部分是以前面几个模块为基础的高级特性模块,实际应用的场景相对较少,主要应用在多线程间相互依赖执行结果场景,没有具体的学习顺序,最好CountDownLatch、CyclicBarrier、Semaphore、Exchanger、Executors都了解下,对后面学习Guava的框架有帮助。

参考资料:
《Java 并发编程的艺术》
https://blog.csdn.net/chen7253886/article/details/52769111
http://ifeve.com/doug-lea/
http://www.cnblogs.com/chenpi/archive/2016/07/06/5614290.html
http://www.cnblogs.com/chenpi/archive/2016/07/06/5614290.html#_label5

并发编程-并发编程的挑战相关推荐

  1. 并发编程的目的和挑战

    并发编程的目的与挑战 并发编程的目的是为了让程序运行得更快.启动更多的线程并不一定就能让程序最大限度地并发执行. 希望通过多线程执行任务让程序运行得更快,会面临非常多的挑战.比如: 上下文切换的问题死 ...

  2. 【洁洁送书第一期】Python高并发与高性能编程: 原理与实践

    这里写目录标题 Python高并发.高性能 解决问题 书本介绍 关于作者 直播预告 Python高并发.高性能 Python成为时下技术革新的弄潮儿,全民Python的发展趋势让人们不再满足于简单地运 ...

  3. 并发编程 | 并发工具类 - 序章

    总览 本章节的思维导图如下所示: 引言 在并发编程的世界中,我们面临着各种复杂的问题,例如线程间的同步.数据一致性保证.任务的分配与执行等.幸运的是,Java提供了一套强大的并发工具类,帮助我们更好地 ...

  4. Go 语言编程 — 并发 — GMP 调度模型

    目录 文章目录 目录 并发和并行 如何交互?CSP 通信模型 如何调度?GMP 调度模型 用户级线程模型(多对一) 内核级线程模型(一对一) 两级线程模型(多对多) GMP 线程模型 Go Runti ...

  5. 基于UDP协议的socket套接字编程 基于socketserver实现并发的socket编程

    基于UDP协议 的socket套接字编程 1.UDP套接字简单示例 1.1服务端 import socketserver = socket.socket(socket.AF_INET,socket.S ...

  6. python并发编程调优_Python并发编程-并发解决方案概述

    Python并发编程-并发解决方案概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.并发和并行区别 1>.并行(parallel) 同时做某些事,可以互不干扰的同一个时 ...

  7. Java并发编程实战_真香!阿里P8耗时半年著作660页Java高并发与网络编程实战总结...

    随着软件行业的飞速发展,互联网公司对开发者的技能要求也越来越高.而高并发.网络编程.微服务.海量数据的处理等技能,是每一个开发者进阶时的必学知识.为了帮助初级开发者快速掌握这些实用技术,本书以&quo ...

  8. Java并发编程实战_阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 为了帮助初级开发者快速掌握高并发.网络编程.微服务.海量数据的处理这些实用技术,本文以"理论+范例"的形式对各个知识点进行了详细的讲解,力争让读者在实践中快速掌握相关知识. ...

  9. C#并行编程-并发集合

    菜鸟学习并行编程,参考<C#并行编程高级教程.PDF>,如有错误,欢迎指正. 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 ...

  10. 阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 有人调侃我们说: 程序员不如送外卖.送外卖是搬运食物,自己是搬运代码,都不产出新的东西-- 透支体力,又消耗健康,可替代性极强,30岁之后就要面临被优化的危险-- 想跳槽,但是更高的平台难进,同 ...

最新文章

  1. Google发布三大新品,Pixel手机价格直逼苹果
  2. MySql JDBC
  3. Hadoop集群中增加与ElasticSearch连接的操作
  4. SharpSvn使用说明
  5. twitter api 无法连接_光大银行牟健君:金融API的安全问题和应对技术
  6. php 秒杀并发怎么做,PHP实现高并发下的秒杀功能–Laravel
  7. mysql中数组转list,Arrays.asList(T... a) 不转换基本类型数组值为list
  8. Spring Boot 之异步执行方法
  9. 指针应用时的注意事项
  10. 国家集训队论文99~08年全版
  11. CentOS7 VMware虚拟机克隆 网卡无法启动问题解决
  12. 【JVM · 字节码】指令集 解析说明
  13. 搞懂这 9 个步骤,DNS 访问原理就明明白白了
  14. AirSim学习(1)-介绍,安装,unity测试
  15. 啥是jQuery(什么是jQuery)
  16. 时间都去哪儿了?互联网3.0时代,好多东西都已“碎片化”
  17. 3GPP TS 29244-g30 中英文对照 | 5.4.15 Packet Rate enforcement
  18. 设计模式之禅-策略模式
  19. hbase批量入库的总结
  20. 越南版微信 zalo 协议分析

热门文章

  1. linux系统读取plc状态,Linux系统下上位机通讯协议及PLC冗余系统组态-工业支持中心-西门子中国...
  2. excel箱形图中位数_在Excel中创建简单的箱形图
  3. 如何查询SCI和EI索引号
  4. linux 行首加特定字符_linux shell 用sed命令在文本的行尾或行首添加字符
  5. Mysql数据库的字段类型
  6. navicat导出数据库数据
  7. 【NVMe2.0b 12】NVM 容量模型
  8. RSTP MSTP
  9. 苹果消息推送服务教程:第一部分(共2部分)
  10. jsp+spring+hibernate