`
这些年
  • 浏览: 389268 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

85977328--并发--开篇

阅读更多

java并发(一)介绍

单CPU:时间切片 
多核多线程CPU:真正的并行 

    如果一个线程在读一个内存时,另一个线程正向该内存进行写操作,那进行读操作的那个线程将获得什么结果呢?是写操作之前旧的值?还是写操作成功之后的新值?或是一半新一半旧的值?或者,如果是两个线程同时写同一个内存,在操作完成后将会是什么结果呢?是第一个线程写入的值?还是第二个线程写入的值?还是两个线程写入的一个混合值?因此如没有合适的预防措施,任何结果都是可能的。而且这种行为的发生甚至不能预测,所以结果也是不确定性的。 
 

在并发编程中,有两个基本的执行单元:进程和线程。在java语言中,并发编程最关心的是线程,然而,进程也是非常重要的。 

即使在只有单一的执行核心的计算机系统中,也有许多活动的进程和线程。因此,在任何给定的时刻,只有一个线程在实际执行。处理器的处理时间是通过操作系统的时间片在进程和线程中共享的。 
现在具有多处理器或有多个执行内核的多处理器的计算机系统越来越普遍,这大大增强了系统并发执行的进程和线程的吞吐量–但在不没有多个处理器或执行内核的简单的系统中,并发任然是可能的。 

进程 
进程具有一个独立的执行环境。通常情况下,进程拥有一个完整的、私有的基本运行资源集合。特别地,每个进程都有自己的内存空间。 
进程往往被看作是程序或应用的代名词,然而,用户看到的一个单独的应用程序实际上可能是一组相互协作的进程集合。为了便于进程之间的通信,大多数操作系统都支持进程间通信(IPC),如pipes 和sockets。IPC不仅支持同一系统上的通信,也支持不同的系统。 
Java虚拟机的大多数实现是单进程的。Java应用可以使用的ProcessBuilder对象创建额外的进程,多进程应用超出了本课的范围。 

线程 
线程有时也被称为轻量级的进程。进程和线程都提供了一个执行环境,但创建一个新的线程比创建一个新的进程需要的资源要少。 
线程是在进程中存在的 — 每个进程最少有一个线程。线程共享进程的资源,包括内存和打开的文件。这样提高了效率,但潜在的问题就是线程间的通信。 
多线程的执行是Java平台的一个基本特征。每个应用都至少有一个线程 – 或几个,如果算上“系统”线程的话,比如内存管理和信号处理等。但是从程序员的角度来看,启动的只有一个线程,叫主线程。这个线程有能力创建额外的线程,

java并发(二)多线程的优点

尽管面临很多挑战,多线程有一些优点使得它一直被使用。这些优点是: 

  • 资源利用率更好
  • 程序设计在某些情况下更简单
  • 程序响应更快


资源利用率更好 
想象一下,一个应用程序需要从本地文件系统中读取和处理文件的情景。比方说,从磁盘读取一个文件需要5秒,处理一个文件需要2秒。处理两个文件则需要: 

5秒读取文件A 
2秒处理文件A 
5秒读取文件B 
2秒处理文件B 
--------------------- 
总共需要14秒 

从磁盘中读取文件的时候,大部分的CPU时间用于等待磁盘去读取数据。在这段时间里,CPU非常的空闲。它可以做一些别的事情。通过改变操作的顺序,就能够更好的使用CPU资源。看下面的顺序: 

5秒读取文件A 
5秒读取文件B + 2秒处理文件A 
2秒处理文件B 
--------------------- 
总共需要12秒 
CPU等待第一个文件被读取完。然后开始读取第二个文件。当第二文件在被读取的时候,CPU会去处理第一个文件。记住,在等待磁盘读取文件的时候,CPU大部分时间是空闲的。 

总的说来,CPU能够在等待IO的时候做一些其他的事情。这个不一定就是磁盘IO。它也可以是网络的IO,或者用户输入。通常情况下,网络和磁盘的IO比CPU和内存的IO慢的多。 

程序设计更优雅 
在单线程应用程序中,如果你想编写程序手动处理上面所提到的读取和处理的顺序,你必须记录每个文件读取和处理的状态。相反,你可以启动两个线程,每个线程处理一个文件的读取和操作。线程会在等待磁盘读取文件的过程中被阻塞。在等待的时候,其他的线程能够使用CPU去处理已经读取完的文件。其结果就是,磁盘总是在繁忙地读取不同的文件到内存中。这会带来磁盘和CPU利用率的提升。而且每个线程只需要记录一个文件,因此这种方式也很容易编程实现。 

程序响应更快 
将一个单线程应用程序变成多线程应用程序的另一个常见的目的是实现一个响应更快的应用程序。设想一个服务器应用,它在某一个端口监听进来的请求。当一个请求到来时,它去处理这个请求,然后再返回去监听。 
服务器的流程如下所述: 
while(server is active){ 
    listen for request 
    process request 

如果一个请求需要占用大量的时间来处理,在这段时间内新的客户端就无法发送请求给服务端。只有服务器在监听的时候,请求才能被接收。另一种设计是,监听线程把请求传递给工作者线程(worker thread),然后立刻返回去监听。而工作者线程则能够处理这个请求并发送一个回复给客户端。这种设计如下所述: 
while(server is active){ 
    listen for request 
    hand request to worker thread 

这种方式,服务端线程迅速地返回去监听。因此,更多的客户端能够发送请求给服务端。这个服务也变得响应更快。 

桌面应用也是同样如此。如果你点击一个按钮开始运行一个耗时的任务,这个线程既要执行任务又要更新窗口和按钮,那么在任务执行的过程中,这个应用程序看起来好像没有反应一样。相反,任务可以传递给工作者线程(word thread)。当工作者线程在繁忙地处理任务的时候,窗口线程可以自由地响应其他用户的请求。当工作者线程完成任务的时候,它发送信号给窗口线程。窗口线程便可以更新应用程序窗口,并显示任务的结果。对用户而言,这种具有工作者线程设计的程序显得响应速度更快。 

java并发(三)多线程的代价

从一个单线程的应用到一个多线程的应用并不仅仅带来好处,它也会有一些代价。不要仅仅为了使用多线程而使用多线程。而应该明确在使用多线程时能多来的好处比所付出的代价大的时候,才使用多线程。如果存在疑问,应该尝试测量一下应用程序的性能和响应能力,而不只是猜测。 
设计更复杂 
虽然有一些多线程应用程序比单线程的应用程序要简单,但其他的一般都更复杂。在多线程访问共享数据的时候,这部分代码需要特别的注意。线程之间的交互往往非常复杂。不正确的线程同步产生的错误非常难以被发现,并且重现以修复。 

上下文切换的开销 
当CPU从执行一个线程切换到执行另外一个线程的时候,它需要先存储当前线程的本地的数据,程序指针等,然后载入另一个线程的本地数据,程序指针等,最后才开始执行。这种切换称为“上下文切换”(“context switch”)。CPU会在一个上下文中执行一个线程,然后切换到另外一个上下文中执行另外一个线程。 
上下文切换并不廉价。如果没有必要,应该减少上下文切换的发生。 
你可以通过维基百科阅读更多的关于上下文切换相关的内容: 
http://en.wikipedia.org/wiki/Context_switch 

增加资源消耗 
线程在运行的时候需要从计算机里面得到一些资源。除了CPU,线程还需要一些内存来维持它本地的堆栈。它也需要占用操作系统中一些资源来管理线程。我们可以尝试编写一个程序,让它创建100个线程,这些线程什么事情都不做,只是在等待,然后看看这个程序在运行的时候占用了多少内存。

 

分享到:
评论

相关推荐

    开篇词-为什么你要学习高并发系统设计?_For_group_share1

    在解答“为什么要学习并发系统设计”之前,我想让你思考个问题:这些问题是你在设计和实现并发系统时经常会遇到的痛点问题,都涉及如何在并发场景下做到性能和可,掌握这些

    01 开篇词-多线程为什么是你必需要掌握的知识.pdf

    Java并发编程学习宝典(漫画版),Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习...

    [ASP.NET MVC 小牛之路] 文章系列

    asp.net mvc系列教程,转载于博客园 一、[ASP.NET MVC 小牛之路]01 - 理解MVC模式 二、[ASP.NET MVC 小牛之路]02 - C#知识点提要 ...二一、[ASP.NET MVC 大牛之路]03 - C#高级知识点概要(2) - 线程和并发

    muduo-master.zip

    muduo是个基于现代C++高效的高并发网络库,他依赖boost库,由陈硕大神编写. muduo代码结构比较清晰易懂,各个细节处理的非常完美,是一个非常值得学习的开源库。基于他是个网络库,开篇我剖析他的网络相关部分的结果...

    用户故事-从“心”出发,我还有无数个可能_For_group_share1

    单纯从我的度出发,除了因为开篇词戳中之外,选择这个课程,还在于想拓宽视野、激发潜能,另,当真的遇到“并发”时,不于望洋兴叹,脑海空。在课程设计上,在课程设计上,

    Java性能调优实战——覆盖80%以上的Java应用调优场景

    开篇词讲怎样才能做好性能调优02讲如何制定性能调优策略04讲慎重使用正则表达式05讲ArrayList还是LinkedList使用不当性能差千倍07讲深入浅出HashMap的设计与优化08讲网络通信优化之IO模型:如何解决高并发下IO瓶颈09...

    应用性能分析实战2021年

    │ 12 并发编程:流量洪峰下,Sentinel 如何高效精准计算?.mp4 │ 13 结构化日志:如何规范数千开发的应用日志?.mp4 │ 14 互通有无:如何设计跨语言的 APM 交互协议?.mp4 │ 15 数据磐石:APM 收集端的存储...

    打造千万级流量秒杀系统2021年

    │ 开篇词 秒杀系统的“三高”架构是怎么炼成的?.mp4 │ 01 功能需求:秒杀业务背景及前端需求是怎么产生的?.mp4 │ 03 非功能需求:高可用、高性能、高并发的指标如何计算?.mp4 │ 06 云架构:基础设施...

    asp.net知识库

    第2章 并发操作的一致性问题 (2) Using sqlite with .NET Visual Studio 2005 中的新 DataSet 特性 MySQL 和 .Net2.0配合使用 与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable 与DotNet数据对象...

    C++网络编程 卷1 运用ACE和模式消除复杂性.part2/2

    《C++网络编程》以一则概论开篇,介绍了撰写分布式并发应用程序时涉及的议题和工具。然后,针对开发灵活、高效的并发式网络应用程序的需要,本书提供了重要的设计空间、模式和原则。本书作者从专家角度向你展示,在...

    C++网络编程 卷1 运用ACE和模式消除复杂性.part1/2

    《C++网络编程》以一则概论开篇,介绍了撰写分布式并发应用程序时涉及的议题和工具。然后,针对开发灵活、高效的并发式网络应用程序的需要,本书提供了重要的设计空间、模式和原则。本书作者从专家角度向你展示,在...

    架构设计面试精讲2021年

    │ 开篇词 中高级研发面试,逃不开架构设计这一环.mp4 │ 01 研发工程师想提升面试竞争力,该具备这三个技术认知.mp4 │ 02 研发工程师如何用架构师视角回答架构设计方案?.mp4 │ 05 海量并发场景下,如何回答...

    Java就业班体系结构文档,Java核心知识,提升Java开发技能、理解Java核心技术及应用场景

    本资源提供了一个循序渐进的学习路径,覆盖了从Java开篇、语法基础、集成开发工具的使用,到面向对象编程、JavaSE进阶学习,再到数据库、前端开发、JavaEE和分布式阶段等多个重要领域。 适用于初学者和有一定经验的...

    搞定后台架构实战指南课2022

    │ 开篇词 跳出单点思维模式,才能真正理解架构设计.mp4 │ 01 为什么不同类型的业务后台架构模式是通用的?.mp4 │ 05 如何做到异构数据的同步一致性?.mp4 │ 07 如何基于流量回放实现读服务的自动化测试回归...

    SQLite学习手册(带目录)

    SQLite学习手册(开篇) 一、简介 二、SQLite的主要优点 三、和RDBMS相比SQLite的一些劣势 四、个性化特征 SQLite学习手册(C/C++接口简介) 一、概述 二、核心对象和接口 三、参数绑定 SQLite学习手册(数据表和视图) 一...

    手把手教你将Flask应用封装成Docker服务的实现

    项目背景   在之前的一个项目中用Python的Flask写了一...点赞过一百的话我整理之后开篇专场如何?说不定里面就有你下一次要采得大坑!而且公司说不定就有你在的或你正准备面的哟 1. 部署准备 Flask:Python Web开发

    ASP.NET组件System.Web.Optimization原理及缓存问题详解

    1】开篇介绍 这篇文章将简单的分析一下有关静态文件捆绑的ASP.NET组件System.Web.Optimization的运行原理及基本的缓存问题: 在我们的项目里面充斥着很多静态文件,为了追求模块化、插件化很多静态文件都被设计成...

Global site tag (gtag.js) - Google Analytics