java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理

1 学习多线程知识的根本目标

多线程知识的根本目标是:设计稳健的并发程序。

当然,本文无法回答这个实践性很强的问题(这与具体的业务相关,涉及到具体的策略),本文主要阐述相关知识之间的关系,希望初学者不要迷失在多线程工具类的API接口中。

2 并发程序的三大宏观问题

线程安全性问题、性能问题、活跃性问题。 三者的关系是,在设计并发程序过程中要首先保证线程安全,在线程安全的基础上努力提升程序性能,在保证线程安全与提升性能时避免引入活跃性问题。

线程安全是最重要的,设计并发程序是为了提升程序的性能,但是永远不要忘记性能是建立在安全的基础上的;而在保证安全性(如加锁、同步等方法)及优化并发性能(如通过锁分解、锁分段等方法)过程中,可能会引入活跃性问题(如死锁、饥饿、活锁、糟糕的响应性等问题)。 本文主要阐述线程安全问题的知识。

3 线程安全性

3.1 线程安全性的定义

当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。最核心的概念就是正确性。正确性的含义是,某个类的行为与其规范完全一致。

就像你要设计一道菜,那么组成这道菜的食材和调料一定是可控的,即你能确切的描述对这些食材和调料操作的结果,比如放油菜会香,放盐菜会咸,并且知道菜快熟时再放盐,只有对构成这道菜的所有元素都清楚明晰,设计出的菜才符合设想。设计程序时也一样,只有使用的各个变量和函数是可控的,设计出的程序才能按照设计运行。而多线程的使用,可能会使得组成程序的某些变量和行为变得不可控。

3.2 为什么多线程会带来线程安全性问题

要阐明线程安全性问题需要深入到JAVA内存模型,这里暂时不引入,这里用两个生活中的例子来阐述线程安全性问题的本质(原子性问题和可见性问题)。

【例1】以炒菜为例。其中有个操作是放盐,放盐的操作可分解为三个步骤“找到盐罐→检查盐罐装的是盐→菜快熟的时候将盐倒入菜中”。如果只有一个人在使用盐罐,那么不会有什么问题。但是,如果在你“检查盐罐中装的是盐”之后,将盐倒入菜中之前,另一个人拿走了盐罐,装了三氯氰胺奶粉,然后将盐罐放回。这个调换过程你并不知道,最后你将调换过的三氯氰胺奶粉倒入了菜中,结果可想而知。这就是线程安全性问题的原子性问题。

从内存模型理解原子性问题:juejin.im/post/684490…

【例2】以A和B协作煮米饭为例。有三个房间(厨房、控火室、观察室),厨房有个锅煮着米饭(锅上有张纸写着“已熟”或者“未熟”),A在控火室负责关火(当看到锅上的纸写着“已熟”时关火),B在观察室负责观察米的状态并修改锅上贴纸的状态字(已熟/未熟);A和B不在一个房间,无法直接交流;B隔一会观察下锅里的米,如果米熟了就在一张纸上写“已熟”,未熟就写“未熟”,B很忙,写完字后将纸贴在了自己门上,未贴在厨房的锅上。最终结果是,A看到锅上的状态字一直是“未熟”,所以不关火,最终米饭糊了。这就是可见性问题。

从内存模型理解可见性问题:juejin.im/post/684490…

3.3 解决原子性问题和内存可见性的核心

要编写线程安全的代码,其核心在于要对状态(变量)访问操作进行管理,特别是对共享的和可变的状态的访问。

共享意味着可由多个线程访问操作,可变意味着可以被修改。

上述例1中,如果盐罐不共享即其他人不能使用,则不会有线程安全性问题。如果规定不能往盐罐中装入,只能从盐罐中取出,那么不管多少个人可以操作盐罐,盐罐中始终是盐,没有线程安全性问题;同样,如果一个变量不能被修改,那么不管多少个线程操作这个变量,也不会带来线程安全性问题。

上述例2中,如果强制B在修改状态字后,将纸贴在锅上,那么就可以让A看到米饭的真正状态,就可以及时关掉火,蒸出香喷喷的米饭。

那么,为了解决原子性问题和内存可见性问题,怎么对共享的且可变的变量进行管理?

除非需要某个域是可变的,否则应将其声明为final域(即声明为不可变的)

将对共享变量的并行操作转换为串行操作(如同步机制、将变量委托给同步容器进行管理)

将共享变量转换为不共享变量(如线程封闭(栈封闭、ThreadLocal类等))

如果某个操作需要以原子方式执行,那么就想办法保证这个操作是原子方式执行(如给操作加锁)

对于需要保证内存可见性的变量,可以强制线程从主内存而不是缓存中读取变量,在线程存储变量时强制存取到主内存中。(如加锁,声明volatile变量)

切记,核心是管理共享的可变状态,锁(内置锁、Lock锁)、同步容器类(Vector、Hashtable等)、并发容器类(ConcurrentHashMap、CopyOnWriteArrayList)、同步工具类(闭锁、信号量、栅栏)、线程池等都只是是管理共享的可变状态的工具。

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

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

相关文章

低代码开发平台_低代码开发平台系列:6、低代码是编程技术发展大势所趋

一、低代码是一种编程技术低代码是快速开发工具/技术的一种,属于软件开发/编程工具/技术领域,主要应用于企业软件开发领域。借助低代码工具,使用者无需编码即可实现企业软件系统常见功能的交付;少量编码扩展更多功能,相…

acm教程 java版_ACM之java速成 (转)

//这里指的java速成,只限于java语法,包括输入输出,运算处理,字符串和高精度的处理,进制之间的转换等,能解决OJ上的一些高精度题目。//1. 输入:// 格式为:Scanner cin new Scanner (…

python网站设计理念_简单介绍下python Django框架的历史,设计理念及优势_Django讲解2...

简单介绍下python Django框架的历史,设计理念及优势Django是一个高层次的 Python Web 框架,它是一个鼓励快速开发和干净,实用的框架设计。Django可以更容易地快速构建更好的Web应用程序,并且它使用更少的代码。注意 − Django是Dj…

abnf java实现_详细讲解如何利用Java实现组合式解析器?

简介:Ward Cunningham 曾经说过,干净的代码清晰地表达了代码编写者所 想要表达的东西,而优美的代码则更进一步,优美的代码看起来就像是专门为了 要解决的问题而存在的。在本文中,我们将展示一个组合式解析器的设计、实…

充电原理_电动汽车充电桩如何设置?充电桩原理介绍

随着新能源产业的蓬勃发展,电动汽车在生活中变得越来越普遍。比亚迪(BYD),宝马(BMW)和特斯拉(Tesla)等汽车制造商都已经推出了全电动汽车,而混合动力汽车则更为普遍。为了能够方便地为这些电动汽车的电池充电,必须建立充电桩。充电…

GUI动画演示java_java – 使用JFrame的简单GUI动画

我覆盖了JFrame中的setVisible()函数.它所做的只是不断增长框架或缩小框架,直到它达到我想要的尺寸.这使得一个简单的动画.我的问题是,它是不稳定的,不平滑的,如果移动框架不能很好地工作.有没有办法可以做到更干净,更流畅,更光滑?/*** Sets this window visible an…

python 抽奖器_如何基于python实现年会抽奖工具

用python来实现一个抽奖程序,供大家参考,具体内容如下主要功能有1.从一个csv文件中读入所有员工工号2.将这些工号初始到一个列表中3.用random模块下的choice函数来随机选择列表中的一个工号4.抽到的奖项的工号要从列表中进行删除,以免再次抽到…

java 获取服务器硬件_dell服务器远程获取硬件状态

以dell的R620型号的服务器做的测试登陆上dell服务器ilo的IP地址,首先打开ipmi,ilo2是直接支持ipmi2.0的此框需要点击 “IDRAC设置”->“网络”->“IPMI设置”在”启用LAN上IPMI“后的复选框打钩,才能启动ipmi好像是内置到了ilo2&#x…

简单可行性报告模板_项目可行性报告模板分享!第三章主要内容

项目可行性报告模板分享!第三章主要内容如下:第三章 市场分析与建设规模市场分析在可行性研究中的重要地位在于,任何一个项目,其生产规模的确定、技术的选择、投资估算甚至厂址的选择,都必须在市场需求情况有了充分的了解后才能解…

java外挂源码_2.7 万 Star!Github 项目源码辅助阅读神器

【导语】:一款用于将 Github 项目代码以树形格式展示的浏览器插件。简介大家平时逛 GitHub 是否会觉得查看源代码的体验十分糟糕?项目文件需要一层层点击,返回也要一层层返回。这样不直观,也比较麻烦。Octotree 是一款辅助阅读 Gi…

php把时间戳转换成字符串,php中将时间差转换为字符串提示的实现代码

如微博这看起来更加人性化,好吧,上代码class timeAgo{static $timeagoObject;private $rustle;private $unit;private function __construct(){}private function __clone(){ }public static function getObject(){if(! (self::$timeagoObject instanceo…

php教育网站设计案例_酒店装修,精品酒店设计装修案例,酒店设计网站

酒店设计需要考虑:设计酒店的时候也要顺应市场潮流,不再单一的提供休息、洗漱、睡觉的空间,还要能提供社交、商务等功能,同顾客产生情况共鸣。这样能够引领生活方式的、能够互动,有仪式感的酒店,是很吸引人…

php数据库数组去重复数据库,PHP查询并删除数据库多列重复数据的方法(利用数组函数实现)...

本文实例讲述了php查询并删除数据库多列重复数据的方法。分享给大家供大家参考,具体如下:$con mysql_connect("localhost","root","");if (!$con){die(could not connect: . mysql_error());}$db_selected mysql_selec…

python创建数据库表空间_7.自动化监控多个Oracle表空间

自动化监控多个Oracle表空间上节讲了如何利用Python自动监控Oracle表空间使用率这节会利用一个循环一次性查询多个表空间使用率环境设置Linux系统为 Centos 6.8Python环境为 Python 3.6orale信息文件其次建立一个新的文本文件存放多个数据库的信息注意最后一行不能是空白行文件…

python采用编译型方式执行_Python程序的执行过程 解释型语言和编译型语言

我初学Python时,听到的关于Python的第一句话就是,Python是一门解释性语言,我就这样一直相信下去,直到发现了*.pyc文件的存在。如果是解释型语言,那么生成的*.pyc文件是什么呢?c应该是compiled的缩写才对啊&…

写一个方法判断一个字符串是否对称_判断一个男生是否好色的方法

▾我们店只招黑喵哦?▾其实也不是不能理解为什么男的要跑?▾有什么相见恨晚的小知识??▾见证奇迹?:是不是穿过去了!?▾医学奇迹?▾卧槽流劈!?真的超光速了!▾细节很到位啊几位少年?▾昨有坟头蹦迪?…

php webserver documentroot,php – 在包含中使用$_SERVER [‘DOCUMENT_ROOT’]是个好主意?...

这是一个好主意吗?require_once($_SERVER[DOCUMENT_ROOT]./include.php);如果在同一台服务器上有两个虚拟主机,一个用于实时,另一个用于开发,具有不同的Apache DocumentRoot,则可避免在包含源未知时包含绝对路径,并且可能位于任何目录中.(注意:下一节中的…

java changestr,java change

VetoableChangeListener (Java Platform SE...2.import java.awt.*; import java.awt.event.*; import javax.swing.*; public class ChangeGUI extends JFrame{ private JButton button; private JLabel ......Java 应用技术实训报告 题 目 万年历记事本 起讫日期 2008 年 6 月…

python读取日志统计ip_如何通过命令行统计和排列访问日志里的ip数

以下的方式速度都会卡在sort上面,数量越多越麻烦。Shell方法:grep -i -o -E -r -e "([0-9]{1,3}\.){3}[0-9]{1,3}" access.log | sort -n | uniq -c | sort -nawk方法:如果是accesslog 格式应该是固定的 会简单些。因为awk做排序也比较的郁闷,…

php斯芬克斯,斯芬克斯之迷——ie私有属性haslayout的困扰

就象神话中的斯芬克斯一样,ie的私有属性haslayout是个神秘且让人困惑的难缠东西,她只游荡于ie(这片沙漠)之下。她无法使用css声明直接创建。即便是对于ie,她也不能说是一个实实在在存在的属性。ie下的元素有些本身拥有haslayout(基本上是一些…