谈一谈Java编程开发中的并发控制

并发指在宏观上的同一时间内同时执行多个任务。为了满足这一需求,现代的操作系统都抽象出 线程 的概念,供上层应用使用。

这篇博文不打算详细展开分析,而是对java并发中的概念和工具做一个梳理。
沿着并发模型、并发要解决的问题、基本工具、衍生工具这一思路展开。

<!-- more -->

线程

首先线程是什么?线程是由OS抽象并实现的,我们知道OS的职责是管理并合理分配硬件资源,那么OS为了更好的管理、分配CPU资源,同时也为了满足同时执行任务这一需求,设计了线程这一概念。

虽然java程序运行在JVM虚拟机上,但是java的线程仍然是对操作系统原生线程的封装,同时,jvm对线程实现时也将jvm的运行栈设计成线程私有内存,因此,java线程和原生线程在理解上实际上没太大区别。

线程的五种状态:

graph LR
新建 --> 就绪;
就绪 --> 运行;
运行 --> 就绪;
运行 --> 阻塞;
阻塞 --> 就绪;
运行 --> 死亡;

先来看上面的就绪状态和运行状态。我们知道线程虽然宏观上是同时执行的,但是微观上使用如时间片轮转算法使得线程依次执行。那么,同一时间只有一个线程执行,其它需要执行的线程处于 就绪队列 中,等待自己被调度到。

而如果线程想要暂时放弃在CPU上运行的权利,就会阻塞自己。这时对应着阻塞状态,同时线程会从就绪队列中移除,进入等待队列。
很显然,阻塞线程被唤醒肯定是进入就绪队列等待调度,而不可能是直接分配到CPU上运行。

在线程同步时,线程可能由于以下情况被阻塞:

  1. 同步阻塞。就是被锁阻塞。
  2. 等待阻塞。被条件变量阻塞。
  3. 其它。调用sleep(), join()或等待IO操作时的阻塞。

并发需要解决的问题

功能性问题

线程同步面临两个问题,想象下有两个线程在协作工作完成某项任务。那么需要解决以下问题:

  1. 线程两个线程之间交互数据,必然涉及到数据共享。而某些数据资源无法被多个线程同时使用(临界区),这时需要,即线程互斥问题。
  2. 假如一个线程进行的太快,另外一个线程就需要等等它,即线程同步问题。

性能和可用性问题

在多线程程序的性能问题上,如果是对于同样一段临界区的多线程访问,那么则有以下几个思路:

  1. 互斥锁。互斥锁即保证同一时间只有一个线程访问临界区并完整执行完,其它线程在临界区外面等待。
  2. 无障碍或无锁。线程们一开始直接进入临界区执行,注意其中不能修改共享数据。执行完后再判断刚才这段时间是否有其它线程执行,没有的话才修改共享数据,如果有的话就回滚重来。
  3. 降低锁粒度。也即将这个大的临界区拆分成几个小的临界区,分别加互斥锁控制,这样提高了线程同时访问的临界区的机会变多,性能提高。显然这要对代码仔细推敲,考虑如何拆分锁粒度而不影响整体的语义。

以上三种思路的性能优劣没有一个普适的结果,和具体的场景相关。

并发中还会出现以下几种情况导致系统不可用:

  1. 死锁。不解释。
  2. 饥饿。线程调度算法如果不是平等分配的,那么就可能出现优先级高的线程长时间占用CPU,导致优先级低的线程无法得到执行机会。
  3. 活锁。这个我解释不来。。。

并发代码的几个性质

并发编程中需要考虑的几个概念:

  1. 原子性:指某个操作一旦被某个线程执行,直到该操作执行完毕都不会有其它线程来干扰。
  2. 可见性:指某个变量或某块内存如果被A线程修改,B线程能否马上读取到修改后的值。
  3. 有序性:A线程执行的代码序列,在B线程看来是否是有序的。

从我个人的理解来看,原子性属于由并发和线程这一理论概念自然而然推导衍生而来的概念,而可见性和有序性是具体的工程实践中产生的。
实际中,jvm并不能实现的特别完美,总会有工程上的妥协。理论模型与实际模型无法完美契合,总存在一定的偏差。
比如说,jvm为了向性能妥协使用了缓存机制,牺牲了数据一致性,这就产生了可见性的概念,需要程序员编程时自己控制。
jvm为了指令更高效率的执行进行了指令重排优化,则产生了有序性的问题。印象里以前大学里学过的CPU的流水线技术,为了指令能够更好的被CPU流水线利用,减少流水线的空闲时间,编译器编译时也会在不影响 串行语义 的前提下,进行指令重排。
总而言之,这是在性能和理论模型完整性之间的一种妥协。

并发的工具

技术上的工具、概念繁多复杂,但是如果我们能理解技术设计上无时无刻的不运用抽象和分层的手段,
那么,我们可以把技术上的工具分为两种:

  1. 最基本的、原生的工具。
  2. 在原生提供的工具上,进行封装得到的更高层次的工具。

更高层次的工具对基础工具进行了抽象和封装,屏蔽了其中的实现细节。
这里想强调的是,工具的接口实现是分开的,两者可以没有关系。
如java的监视器锁从接口上来看,其语义和互斥锁一样。然而它并不一定使用互斥锁实现,而是可以为了性能存在优化,只要最终的行为与接口相同即可。

基本工具

锁、条件变量、信号量

有三种用于线程同步的工具:

  1. 锁。锁可用于规定一个 临界区,同一时间临界区内仅能由一个线程访问。其他线程则在临界区外等待(阻塞)。
  • 互斥锁。使用信号量实现。临界区外等待的线程会被阻塞。
  • 自旋锁。临界区外等待的线程会忙等。

 

  1. 条件变量(Condition)。线程在某种条件不满足时阻塞自己,等待其它的线程条件满足时再唤醒它们。很显然所有等待的线程要放入一个数据结构中,这个数据结构就在条件变量内。
  2. 信号量。操作系统原生的机制。实际上,锁 + 条件变量可完成所有信号量可以完成的逻辑。

在java中,Object类有wait()、notify()和notifyAll()之类的方法。
这些方法可以认为每个对象都内置了一个条件变量,而这些方法是对这些条件变量的操作,因此,可以使用这些方法将对象当作条件变量使用,从而做到线程的同步。

为了让学习变得轻松、高效,今天给大家免费分享一套Java入门教学资源。帮助大家在成为Java架构师的道路上披荆斩棘。需要资料的欢迎加入学习交流群:9285,05736

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/503262.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言中头文件及其作用,C语言头文件的作用是什么

C语言头文件的作用&#xff1a;1、头文件是程序各部分之间保证信息一致性的桥梁&#xff0c;是连接程序对象定义和使用的纽带&#xff1b;2、用于指定模块接口的声明放在文件中&#xff0c;文件名中应标明其预期用途。本文操作环境&#xff1a;Windows7系统&#xff0c;宏基S40…

Java技术大咖为什么都有写博客的习惯呢?

把自己的设计、思路、总结都写到日记里&#xff08;我用evernote&#xff09;&#xff0c;便于自己思路的整理&#xff0c;很多时候人脑的缓存是真不够用&#xff0c;后面回来找思路的时候&#xff0c;细节也都在笔记里面。 1.让我思维更清晰&#xff0c;表述更有条理 我生活中…

奥鹏20年12月作业考核(C语言专科),《C语言(专科)》20年12月作业考核【答案100分】...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼《C语言(专科)》20年12月作业考核共20道题 总分&#xff1a;100分100分咨询dddda98咨询dddda98咨询dddda98单选题一、单选题共20题&#xff0c;100分15分请选出可用作C语言用户标识符的一组标识符( )Avoid define WORDBa3_b3 _123 …

Java与C++有何区别呢?请看以下几点就明白了……

Java和C都是面向对象语言。也就是说&#xff0c;它们都能够实现面向对象思想。那两者到底有何区别&#xff1f;由于c为了照顾大量的C语言使用者&#xff0c; 而兼容了C&#xff0c;使得自身仅仅成为了带类的C语言&#xff0c;多多少少影响了其面向对象的彻底性&#xff01;JAVA…

零基础学习java必须要了解的学习路线

Java开发目前热火朝天&#xff0c;但是有传言说Java将被取代&#xff0c;当然那只是传言。今天小编来谈谈零基础学习Java必须了解的学习路线。 第一阶段&#xff1a;HTMLCSS 静态布局开始 有人肯能会说我是做后端的&#xff0c;前端的事情不用管&#xff0c;这本身就是一个误区…

linux相关英文书记,Linux常用软件(英文介绍)

Linux常用软件(英文介绍)发布时间:2007-09-27 15:37:36来源:红联作者:wsecurotyFirefoxThe best internet browserAmaroKThe most sophisticated mp3 player for Linuxk3bK3b is a feature-rich and easy to handle CD burning application.ThunderbirdThe best email clientba…

linux openoffice centos,centos8 openoffice安装

安装桌面GUIyum check-updateyum -y install lvm2 device-mapperyum -y groupinstall GNOME1. 首先下载rpm包下载rpm包(官网或者其他网站都可以)但是要注意版本,我建议是4.1.2版本以上,因为以前的版本不支持含有中文的文件名的文档转pdf;我下载的是这个Apache_OpenOffice_4.1.3…

Java开发以及Web 和移动程序员必须了解的10个框架

新的一年已经开始&#xff0c;不知道大家有没有定好小目标。如果2019年还没有决定学什么&#xff0c;那么你来对地方了。在今天的文章中&#xff0c;我将分享一些你可以学习的最好框架&#xff0c;以提升你在移动和Web开发以及大数据技术方面的知识。 在当今世界&#xff0c;对…

c语言在机械专业的应用,高职院校机械类C语言程序设计教学改革探讨

摘 要&#xff1a;C语言程序设计作为高职院校机械类专业公共课程&#xff0c;对于培养学生快速掌握计算机程序设计的能力&#xff0c;更快地适应后续专业课程的学习是很重要的。所以就需要本课程老师能按照本门课程的定位以及机械类专业的需求&#xff0c;较好的实施教学内容的…

Java开发学习必须了解的基础知识点

面向对象和面向过程的区别 面向过程&#xff1a; 优点&#xff1a;性能比面向对象高&#xff0c;因为类调用时需要实例化&#xff0c;开销比较大&#xff0c;比较消耗资源;比如单片机、嵌入式开发、Linux/Unix等一般采用面向过程开发&#xff0c;性能是最重要的因素。 缺点&a…

电子琴仿真c语言程序,矩阵键盘模拟电子琴C语言程序设计

原标题&#xff1a;矩阵键盘模拟电子琴C语言程序设计//24c08地址为0xa0#include #define uchar unsigned charunsigned char code table[]{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};unsigned char sec0; //定义计数值,每过1秒,sec加1unsigned int count; //定时中断…

Java的数据类型及其封装器类

Java基本类型共有8种&#xff0c;基本类型可以分为3类&#xff0c;字符类型char&#xff0c;布尔类型boolean和数值类型byte、short、int、long、float、double。数值类型又可以分为整数类型byte、short、int、long和浮点数类型float、double。JAVA中的数值类型不存在无符号的&…

c语言字符为0和1,//C语言:将一个由字符0和1组成的表示二进制数的字符串,转换成相应的十进制数返回。...

//函数fun:将一个由字符0和1组成的表示二进制数的字符串&#xff0c;转换成相应的十进制数返回。#include #pragma warning (disable:4996)#define N 16/**********************found***********************/int fun( char s[]) //形参不要使用定值{ int i, n ;/************…

Java开发中数据类型之间的转换

1).简单类型数据间的转换,有两种方式:自动转换和强迫转换,通常产生在表达式中或方法的参数传递时。 自动转换 具体地讲,当1个较"小"数据与1个较"大"的数据1起运算时,系统将自动将"小"数据转换成"大"数据,再进行运算。而在方法调用时…

单片机c语言怎样添加自定义头文件,单片机C语言编程与或|头文件常见问题

一、常见问题1、头文件reg51.h和reg52.h其实是一样的&#xff0c;大家两个都可以用。2、main()前面的void可加可不加&#xff0c;反正都是无返回值函数。3、不是每一个程序都要用到死循环while(1)&#xff0c;例如点亮一颗LED小灯就不用&#xff0c;只要执行一次就一直是高电平…

c语言栈指针移动原理,C指针原理(4)-ATamp;T汇编

首先我们先用汇编编写一个helloworld&#xff0c;注意我们直接在汇编代码中调用C语言的printf函数将"hello,world\n" 输出在屏幕上。.section .dataoutput:.asciz "hello,world\n".section .text.global mainmain:push $outputcall printfaddl $4,%esppus…

为什么码农要了解业务呢?网友:不是敲代码就好了吗?

分析领域的一位资深人士对我非常无助地摇了摇头。 “这个程序员&#xff0c;不要吃烟花&#xff01;”我也深深感到世界各地的农民代码都是一样的。 这让我想起了它&#xff0c;也是他。很多年前我提醒过我。——关注业务。从那以后&#xff0c;我一直在匆匆走上技术商业的双重…

c语言中 include math.h,C语言中的(#includestdio.h和#includemath.h)是什么意思?

慕码人2483693include 称为文件包含命令&#xff0c;其作用是把尖括号""或引号<>内指定的文件包含到本程序中&#xff0c;成为本程序的一部分&#xff0c;被包含的文件通常是由系统提供的&#xff0c;其扩展名为.h stdio.h就是指“standard input&output&q…

论程序员如何规划职业路线?网友:从码农到工程师?

很多人可以说对这个话题两个字&#xff0c;三年或五年以上工作经验的编程&#xff0c;老建筑师&#xff0c;设计师&#xff0c;技术副总裁&#xff0c;首席技术官&#xff0c;和自己的观点和实践经验。没有一种方法适合每个人。这套针对软件工程师的专业开发计划只是您在旅途中…

c语言实现socket转json,C++实现json形式的Socket传输图片

本文实例为大家分享了C实现json形式的Socket传输图片的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下大致流程&#xff1a;客户端读取图片&#xff0c;经过Base64编码&#xff0c;转成字符串的形式&#xff0c;保存到json中&#xff0c;通过socket传到服务端&#x…