热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

java并发编程的艺术第一章

这个写出来,纯属自娱自乐,以后还得再改正。什么是并发编程?

这个写出来,纯属自娱自乐,以后还得再改正。

什么是并发编程?

并发编程目的是为了让程序运行的更快(也不是线程越多,越快,这里会遇到很多的问题,不如上下文切换问题死锁的问题,以及受限于硬件软件的资源限制)

 

上下文切换(任务从保存到再加载的过程)(类似于我们玩的单机游戏的存档,可以不同的人来玩一样)

什么是上下文切换?

是指CPU从一个进程或者线程切换到另一个进程或者线程

剩下文切换的步骤?

1 挂起一个进程或者线程,将这个线程在cpu中的状态(对,没错这个状态就叫做上下文)存储在内存中的某处 2 在线程中检索写一个线程的上下文并在CPU寄存器中恢复3跳转到上一个线程被中断的代码行(我想这也就是需要程序计数器和寄存器的原因,抱歉寄存器我现在都还没搞懂)

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

 

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

 

上下文的切换是会影响效率(任务的执行时间)的,同样上下文切换也会影响多线程的执行速度。

 

减少上下文切换实战

类似于上面的这个例子serial()方法是单线程的执行时间测试concurrency()是多线程的时间效率的测试。

那么当操作不超过百万次时,并发会比串行的执行速度要慢,为什么会产生这种情况,因为线程有创建上下文切换的开销。

 

那我们就来测试一下上下文切换的次数和时间的长短 具体来看看


cs可以看出上下文切换,每隔一秒就要切换1000多次。也就是切换一次需要1ms喽,也就是说当我们执行一段程序时,上下文在不停的切换,增加了我们的执行书时间。

 

如何减少上下文的切换

具体有(无锁并发编程,CAS算法,使用最少线程和使用协程)

无锁并发编程:多线程竞争锁时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照HaSh算法取模分段,不同的线程处理不同段的数据(这里我不太清楚他指的数据是什么数据?一般for循环不都是每一一个数据吗?(这里应该指的是多核处理器执行吧))

 

CAS算法:javaAtomic包使用CAS算法来更新数据,而不需要加锁。

 

使用最少线程:这个比较简单,就是避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量的线程都处于等待状态(我就想不通,难道处于等待状态的线程也会浪费时间?想通了,当线程创建的时候是NEW状态,然后创建完成之后就成了Runnable状态,这个转换是需要时间的,这里的比如执行一个任务,我们有两个线程AB的话,那么这个任务肯定就要不就是线程A执行 要不就是线程B执行,切换频率肯定小,而且因为我们的处理器处理的线程是有限的,如果100个的话,那么谁做还不确定,有空闲的线程,在等待回调消息之后有可能就直接切换别的线程进行执行了,所以上下文切换比较多)

 

 

协程:在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换(哇这什么鬼,难道在绕口令吗,还是我太菜了 其实是当一个线程执行一个任务的时间片段到了之后,然后需要自己手动中断,然后保存上下文的状态,然后让这个线程再继续执行下面的直到任务结束,相当于单任务的多线程单核执行吧 ,而且是和多线程一块进行,互不影响)




死锁

锁我们经常使用,但是它也会给我们带来一些困扰,那就是可能会引起死锁,一旦产生死锁,就会造成系统功能不可用。

A等待B释放B等待A释放 造成无限死循环 就会造成死锁

当然显示情况中我们并不会写出这样的代码,但是在我们写的过程中,比如线程A拿到了锁,但是因为一些异常,没有释放这个锁,或者说,线程A拿到了一个数据库锁,释放锁的时候抛出了异常,没释放掉,一旦出现死锁,业务就得停止,那么就只能通过dump线程查看到底是哪个线程出现了问题。

通过dump线程查看到的结果,他会告诉你是哪个类的多少行引起了死锁,对应我们上边的就是,4231

 

下面我们来介绍避免死锁的几个常见方法

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

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

阐释使用定时锁使用lock.tryLock(timeout)来替代使用内部锁机制

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

 

资源限制的挑战

 

1什么是资源限制

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

2资源限制引发的并发问题

在并发编程的过程中,将代码执行加快的原则是将代码中串行执行的部分编程并发编程

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

3如何解决资源限制问题

对于硬件资源的限制,我们可以考虑集群并行程序,既然单机的资源有限制,那就在多机上进行运行。

对于软件资源限制,可以考虑使用资源池将资源复用,比如使用连接池连接数据库和socket连接复用,


推荐阅读
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 2023年京东Android面试真题解析与经验分享
    本文由一位拥有6年Android开发经验的工程师撰写,详细解析了京东面试中常见的技术问题。涵盖引用传递、Handler机制、ListView优化、多线程控制及ANR处理等核心知识点。 ... [详细]
  • 并发编程:深入理解设计原理与优化
    本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ... [详细]
  • MySQL索引详解与优化
    本文深入探讨了MySQL中的索引机制,包括索引的基本概念、优势与劣势、分类及其实现原理,并详细介绍了索引的使用场景和优化技巧。通过具体示例,帮助读者更好地理解和应用索引以提升数据库性能。 ... [详细]
  • 本文将详细介绍如何在Linux操作系统中执行PHP脚本,包括环境配置、命令使用及验证方法。对于需要在Linux环境下开发或部署PHP应用的用户来说,这是一篇非常实用的文章。 ... [详细]
  • 本文探讨了 Spring Boot 应用程序在不同配置下支持的最大并发连接数,重点分析了内置服务器(如 Tomcat、Jetty 和 Undertow)的默认设置及其对性能的影响。 ... [详细]
  • 本文介绍如何解决在 IIS 环境下 PHP 页面无法找到的问题。主要步骤包括配置 Internet 信息服务管理器中的 ISAPI 扩展和 Active Server Pages 设置,确保 PHP 脚本能够正常运行。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 本文详细介绍了如何使用PHP检测AJAX请求,通过分析预定义服务器变量来判断请求是否来自XMLHttpRequest。此方法简单实用,适用于各种Web开发场景。 ... [详细]
  • 本文详细介绍了如何在Ubuntu系统中下载适用于Intel处理器的64位版本,涵盖了不同Linux发行版对64位架构的不同命名方式,并提供了具体的下载链接和步骤。 ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
author-avatar
叶韵
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有