并发编程的目的是为了让程序运行得更快,但并不是启动更多的线程就能让程序最大限度地并发执行。在进行并发编程时,如果希望通过过线程执行任务让程序运行得更快,会面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题。

上下文切换

即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。

CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后会切换到下一个任务。但是,在切换前会保存上一个任务的状态,以便下次切换回这个任务时,可以再加载这个任务的状态。所以任务从保存到再加载的过程就是一次上下文切换。

上下文切换会影响多线程的执行速度,减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。

  • 无锁并发编程

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

  • CAS算法

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

  • 使用最少线程

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

  • 协程

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

死锁

锁是个非常有用的工具,运用场景非常多,因为它使用起来非常简单,而且易于理解。但同时它也会带来一些困扰,那就是可能会引起死锁,一旦产生死锁,就会造成系统功能不可用。

死锁代码示例:

public class DeadLock{private Object lockOne = new Object();private Object lockTwo = new Object();public void methodOne() {synchronized (lockOne){try {Thread.sleep(5000l);} catch (InterruptedException e) {//}methodTwo();}}public void methodTwo() {synchronized (lockTwo){try {Thread.sleep(5000l);} catch (InterruptedException e) {}methodOne();}}public static void main(String[] args) {DeadLock deadLock = new DeadLock();new Thread(new Runnable() {@Overridepublic void run() {deadLock.methodOne();}}).start();new Thread(new Runnable() {@Overridepublic void run() {deadLock.methodTwo();}}).start();}
}
复制代码

一旦出现死锁,业务是可感知的,因为不能继续提供服务了,那么只能通过dump线程查看到底是哪个线程出现了问题。避免死锁的几个常见方法:

  • 避免一个线程同时获取多个锁

  • 避免一个线程在锁内同时占用多个资源,尽量保证每个锁只占用一个资源。

  • 尝试使用定时锁,使用lock.tryLock(timeout)来替代使用内部锁机制。

  • 对于数据库锁,加锁和解锁必须在一个数据库连接里,否则会出现解锁失败的情况。

资源限制的挑战

  • 什么是资源限制

    资源限制是指在进行并发编程时,程序的执行速度受限于计算机硬件资源或软件资源。例如,服务器的带宽只有2Mb/s,某个资源的下载速度是1Mb/s每秒,系统启动10个线程下载资源,下载速度不会变成10Mb/s,所以在进行并发编程时,要考虑这些资源的限制。硬件资源限制有带宽的上传/下载速度、硬盘读写速度和CPU的处理速度。软件资源限制有数据库的连接数和socket连接数等。

  • 资源限制引发的问题

    在并发编程中,将代码执行速度加快的原则是将代码中串行执行的部分变成并发执行,但是如果将某段串行的代码并发执行,因为受限于资源,仍然在串行执行,这时候程序不仅不会加快执行,反而会更慢,因为增加了上下文切换和资源调度的时间。

  • 如何解决资源限制的问题

    对于硬件资源限制,可以考虑使用集群并行执行程序。既然单机的资源有限制,那么就让程序在多机上运行。比如使用ODPS、Hadoop或者自己搭建服务器集群,不同的机器处理不同的数据。可以通过“数据ID%机器数”,计算得到一个机器编号,然后由对应编号的机器处理这笔数据。对于软件资源限制,可以考虑使用资源池将资源复用。比如使用连接池将数据库和Socket连接复用,或者在调用对方webservice接口获取数据时,只建立一个连接。

  • 在资源限制情况下进行并发编程

    如何在资源限制的情况下,让程序执行得更快呢?方法就是,根据不同的资源限制调整程序的并发度,比如下载文件程序依赖于两个资源——带宽和硬盘读写速度。有数据库操作时,涉及数据库连接数,如果SQL语句执行非常快,而线程的数量比数据库连接数大很多,则某些线程会被阻塞,等待数据库连接。

参考资料

Java并发编程的艺术

欢迎留言补充,共同交流。个人微信公众号求关注

Java并发系列—并发编程挑战相关推荐

  1. java io 并发编程,JAVA进阶系列 - 并发编程 - 第1篇:进程线程并发并行

    学习目标进程 线程 并发 并行 内容 一.进程与线程 "专业"点的说法就是:进程是资源分配的最小单位,线程是CPU调度的最小单位. 大哥,我错了,别打脸! 进程 线程就是用来加载指 ...

  2. Java面试系列之并发编程专题-Java线程池灵魂拷问

    金三银四跳槽季即将来临,想必有些猿友已经蠢蠢欲动在做相关的准备了!在接下来的日子里,笔者将坚持写作.分享Java工程师在面试求职期间的方方面面,包括简历制作.面试场景复现.面试题解答.谈薪技巧 以及 ...

  3. 《Java线程与并发编程实践》—— 2.3 谨防活跃性问题

    本节书摘来异步社区<Java线程与并发编程实践>一书中的第2章,第2.3节,作者: [美]Jeff Friesen,更多章节内容可以访问云栖社区"异步社区"公众号查看. ...

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

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

  5. Java多线程系列(七):并发容器的原理,7大并发容器详解、及使用场景

    之前谈过高并发编程系列: 高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 高并发编程系列:CountDownLatch.Semaphore等4大并发工具类详解 高并发编程系列:4大J ...

  6. Java多线程系列(九):CountDownLatch、Semaphore等4大并发工具类详解

    之前谈过高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景 ,以及高并发编程系列:ConcurrentHashMap的实现原理(JDK1.7和JDK1.8) 今天主要介绍concurre ...

  7. Java多线程与并发系列从0到1全部合集,强烈建议收藏!

    在过去的时间中,我写过Java多线程与并发的整个系列. 为了方便大家的阅读,也为了让知识更系统化,这里我单独把Java多线程与并发的整个系列一并罗列于此,希望对有用的人有用,也希望能帮助到更多的人. ...

  8. java书籍_还搞不定Java多线程和并发编程面试题?你可能需要这一份书单!

    点击蓝色"程序员书单"关注我哟 加个"星标",每天带你读好书! ​ 在介绍本书单之前,我想先问一下各位读者,你们之前对于Java并发编程的了解有多少呢.经过了1 ...

  9. java 多线程 最优_Java多线程与并发系列从0到1全部合集,强烈建议收藏!

    在过去的时间中,我写过Java多线程与并发的整个系列. 为了方便大家的阅读,也为了让知识更系统化,这里我单独把Java多线程与并发的整个系列一并罗列于此,希望对有用的人有用,也希望能帮助到更多的人. ...

最新文章

  1. 苏黎世联邦理工学院SML课题组招收统计机器学习全奖博士生
  2. 蓝牙怎么实现传输的_不知道手机蓝牙有啥用?1分钟带你了解蓝牙这6种用法!涨知识啦...
  3. 【HDU2582 关于 gcd( C[n][1],C[n][2],C[n][3],........C[n][n-1) 】
  4. Socket编程:必须要了解的网络字节序和转换函数
  5. 龙芯linux内核,龙芯的linux kernel,内核开发与编译
  6. 优化算法的意义,之二。
  7. C语言的atoi和C++的to_string
  8. 程序员面试金典 - 面试题 10.11. 峰与谷(排序/不排序)
  9. 关于web前端中文站(www.lisa33xiaoq.net)侵权业余草(www.xttblog.com)相关文章的公告...
  10. 网站服务器系统组成,linux系统由哪几部分组成_网站服务器运行维护,linux
  11. 使用Gitosis搭建Git服务器
  12. 机器学习算法篇:最大似然估计证明最小二乘法合理性
  13. 和程序员男友过节是这样的
  14. python中文文本聚类_Python3文本聚类如何进行分类操作?
  15. 南大计算机面经(结果:WaitList)
  16. YII2调用天翼云OOS 对象存储服务
  17. 求一个十六进制数的各二进制位_C语言实现
  18. 【C++面试必备】一个专栏带你搞定剑指offer第二版
  19. 数组、链表、哈希、队列、栈数据结构特点,各自优点和缺点
  20. 信安学习-day13

热门文章

  1. 用户访一个APP或者网页流程示意图
  2. 2014.10.1 Form中显示pdf文件
  3. grep命令与正则表达式
  4. poj 3335 Rotating Scoreboard - 半平面交
  5. 免费UNIX体验中心
  6. Palo Alto Networks 支持仪表盘漏洞泄露数千份客户支持工单
  7. python下使用pymongo操作mongodb
  8. linux中程序包管理方式出现的原由(转载)
  9. Smali动态调试方法
  10. linux centos6.5下安装svn方法