并发执行变成串行_网易Java研发面试官眼中的Java并发——安全性、活跃性、性能...

2eea90e0acc6d5a7ebe6eef12d691f6d.png

一. 安全性问题

  1. 线程安全的本质是正确性,而正确性的含义是程序按照预期执行
  2. 理论上线程安全的程序,应该要避免出现可见性问题(CPU缓存)、原子性问题(线程切换)和有序性问题(编译优化)
  3. 需要分析是否存在线程安全问题的场景:存在共享数据且数据会发生变化,即有多个线程会同时读写同一个数据
  4. 针对该理论的解决方案:不共享数据,采用线程本地存储(Thread Local Storage,TLS);不变模式

Ⅰ. 数据竞争

数据竞争(Data Race):多个线程同时访问同一数据,并且至少有一个线程会写这个数据

1. add

private static final int MAX_COUNT = 1_000_000;private long count = 0;// 非线程安全public void add() { int index = 0; while (++index < MAX_COUNT) { count += 1; }}

2. add + synchronized

private static final int MAX_COUNT = 1_000_000;private long count = 0;public synchronized long getCount() { return count;}public synchronized void setCount(long count) { this.count = count;}// 非线程安全public void add() { int index = 0; while (++index < MAX_COUNT) { setCount(getCount() + 1); }}
  • 假设count=0,当两个线程同时执行getCount(),都会返回0
  • 两个线程执行getCount()+1,结果都是1,最终写入内存是1,不符合预期,这种情况为竟态条件

Ⅱ. 竟态条件

  1. 竟态条件(Race Condition):程序的执行结果依赖于线程执行的顺序
  2. 在并发环境里,线程的执行顺序是不确定的
  • 如果程序存在竟态条件问题,那么意味着程序的执行结果是不确定的

1. 转账

public class Account { private int balance; // 非线程安全,存在竟态条件,可能会超额转出 public void transfer(Account target, int amt) { if (balance > amt) { balance -= amt; target.balance += amt; } }}

Ⅲ. 解决方案

面对数据竞争和竟态条件问题,可以通过互斥的方案来实现线程安全,互斥的方案可以统一归为锁

ba164d61c6fe7ad4700e0aa616abcbe2.png

二. 活跃性问题

活跃性问题:某个操作无法执行下去,包括三种情况:死锁、活锁、饥饿

Ⅰ. 死锁

  1. 发生死锁后线程会相互等待,表现为线程永久阻塞
  2. 解决死锁问题的方法是规避死锁(破坏发生死锁的条件之一)
  • 互斥:不可破坏,锁定目的就是为了互斥
  • 占有且等待:一次性申请所有需要的资源
  • 不可抢占:当线程持有资源A,并尝试持有资源B时失败,线程主动释放资源A
  • 循环等待:将资源编号排序,线程申请资源时按递增(或递减)的顺序申请

Ⅱ. 活锁

  • 活锁:线程并没有发生阻塞,但由于相互谦让,而导致执行不下去
  • 解决方案:在谦让时,尝试等待一个随机时间(分布式一致算法Raft也有采用)

Ⅲ. 饥饿

  1. 饥饿:线程因无法访问所需资源而无法执行下去
  • 线程的优先级是不相同的,在CPU繁忙的情况下,优先级低的线程得到执行的机会很少,可能发生线程饥饿
  • 持有锁的线程,如果执行的时间过长(持有的资源不释放),也有可能导致饥饿问题
  1. 解决方案
  • 保证资源充足
  • 公平地分配资源(公平锁) – 比较可行
  • 避免持有锁的线程长时间执行
6e73018f0589c38a236c85e78fac42de.png

三. 性能问题

  1. 锁的过度使用可能会导致串行化的范围过大,这会影响多线程优势的发挥(并发程序的目的就是为了提升性能)
  2. 尽量减少串行,假设串行百分比为5%,那么多核多线程相对于单核单线程的提升公式(Amdahl定律)
  3. S=1/((1-p)+p/n),n为CPU核数,p为并行百分比,(1-p)为串行百分比
  • 假如p=95%,n无穷大,加速比S的极限为20,即无论采用什么技术,最高只能提高20倍的性能

Ⅰ. 解决方案

  1. 无锁算法和数据结构
  • 线程本地存储(Thread Local Storage,TLS)
  • 写入时复制(Copy-on-write)
  • 乐观锁
  • JUC中的原子类
  • Disruptor(无锁的内存队列)
  1. 减少锁持有的时间,互斥锁的本质是将并行的程序串行化,要增加并行度,一定要减少持有锁的时间
  • 使用细粒度锁,例如JUC中的ConcurrentHashMap(分段锁)
  • 使用读写锁,即读是无锁的,只有写才会互斥的

Ⅱ. 性能指标

  1. 吞吐量:在单位时间内能处理的请求数量,吞吐量越高,说明性能越好
  2. 延迟:从发出请求到收到响应的时间,延迟越小,说明性能越好
  3. 并发量:能同时处理的请求数量,一般来说随着并发量的增加,延迟也会增加,所以延迟一般是基于并发量来说的

写在最后

  • 第一:看完点赞,感谢您的认可;
  • ...
  • 第二:随手转发,分享知识,让更多人学习到;
  • ...
  • 第三:记得点关注,每天更新的!!!
  • ...

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

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

相关文章

Mybatis框架中SqlSessionFactory

首先SqlSessionFactory与SqlSession都是同一个接口 SqlSessionFactory是通过SqlSessionFactoryBuilder的build方法创建的 而build方法创建的是一个SqlSessionFactory的实现类,叫DefaultSqlSessionFactory 然后这个实现类主要用的设计模式是建造者(build)模式,而里面最终要达…

cpu模拟器c语言实现_你写出来的C语言是这样调用硬件的!

大家都知道我们可以使用C语言写一段程序来控制硬件工作&#xff0c;但你知道其工作原理吗&#xff1f;网友北极C语言在实际运行中&#xff0c;都是以汇编指令的方式运行的&#xff0c;由编译器把C语言编译成汇编指令&#xff0c;CPU直接执行汇编指令。所以这个问题就变成&#…

apk瘦身

原文地址&#xff1a;http://blog.coderclock.com/2017/01/24/android/Android%E5%BA%94%E7%94%A8%E7%98%A6%E8%BA%AB%EF%BC%8C%E4%BB%8E18MB%E5%88%B012.5MB/ Android应用瘦身&#xff0c;从18MB到12.5MB 开篇语 前阵子老大交给了我一个任务&#xff0c;主要是帮我们开发的直播…

交叉连接(笛卡尔积)

一。什么是笛卡尔积&#xff08;交叉连接&#xff09; 交叉连接&#xff08;Cross Join&#xff09;&#xff0c;又称“笛卡尔连接&#xff08;Cartesian Join&#xff09;”或“叉乘&#xff08;Product&#xff09;”&#xff0c;它是所有类型的内连接的基础。 如果把表视为…

java删除字符串最后一位

String s "1,2,3,4,5,6,7,8,";//目标&#xff1a;删除最后一个 ","s s.substring(0, s.length() - 1);System.out.println(s);

内连接查询的重点分析

一。概要 内连接基于连接谓词&#xff0c;它将两张表 ( 如A 和 B) 的列组合在一起&#xff0c;产生新的结果表。 内连接查询会将 A 表的每一行和 B 表的每一行进行比较&#xff0c;并找出满足连接谓词的组合。当连接谓词被满足&#xff0c;A 和 B 中匹配的行会按列组合&#x…

杨森翔的书法【斗方】

转载于:https://www.cnblogs.com/ysx4221/p/6568171.html

最后一条记录_幸好朋友圈没有访客记录。

以前玩QQ的时候&#xff0c;一定要开个黄钻。因为去偷窥喜欢的男孩的空间&#xff0c;非黄钻可以选择删除此条访问记录&#xff0c;但黄钻可以设置“对其隐身访问”。这样看完之后不仅没有了访客记录&#xff0c;就连在看的过程中也不会被发现。毕竟&#xff0c;我每次在他空间…

安卓UI测试(基于android studio环境 espresso框架)

用户登录界面测试&#xff0c;在新包里新建一个测试类如图 测试代码如下 1 public class AndroidTest {2 private static final String a "peter";3 Rule4 public ActivityTestRule<MainActivity> mActivityRule5 new ActivityTestR…

mybatis使用statement.getGenreatedKeys(); useGeneratedKeys=”true”;使用自增主键获取主键值策略和Oracle不支持自增,Oracle使用序列

parameterType: 参数类型&#xff0c; 可以省略 mysql支持自增主键&#xff0c;自增主键的获取&#xff0c; mybatis也是利用statement.getGenreatedKeys(); useGeneratedKeys”true”&#xff1b;使用自增主键获取主键值策略 keyProperty&#xff1b;指定对应的主键属性&…

Embeded linux之移植boa

一、解压 a) tar xvf boa-0.94.13.tar.gz 二、设置交叉编译工具 a) vi /boa-0.94.13/src/Makefile b) 三、修改源码 a) vi /boa-0.94.13/src/compat.h b) c) vi /boa-0.94.13/src/log.c d) e) vi /boa-0.94.13/src/boa.c f) g) vi /boa-0.94.13/src/boa.conf h) 四、编译 …

待遇 新时达机器人_践行中国制造2025:工业机器人企业突围之路

(一)工业机器人产业突围任重道远工业机器人是实施自动化生产线、工业4.0、智能制造车间、数字化工厂、智能工厂的重要基础装备之一&#xff0c;为贯彻落实好《中国制造2025》将机器人作为重点发展领域的总体部署&#xff0c;推进我国机器人产业快速健康可持续发展&#xff0c;《…

常用类回顾之(String类)

String类&#xff1a; String类:表示不可变的字符串,当前对象创建完毕之后,该对象的内容(字符序列)是不能改变的,一旦内容改变就是一个新的对象. String对象的创建: 1):直接赋一个字面量: String str1 “ABCD”; 2):通过构造器创建: String str2 new String(“ABCD”); 两种方…

ad如何设置pcb板子形状_俺老孙画个圈板框与安装孔PCB系列教程110

点击上方蓝字关注我们画个板子&#xff0c;要先划圈&#xff0c;把所有笨蛋元器件圈起来。这个圈&#xff0c;就是板子的边框&#xff0c;简称板框。自定义板框形状比较复杂的电路板&#xff0c;一般由专业的CAD结构工程师设计&#xff0c;并提供DWG或者DXF格式的文件给电子工程…

Mybatis查询传递单个参数和传递多个参数用法

一&#xff1a;单个参数&#xff0c;Mybatis不会做特殊处理 二&#xff1a;多个参数&#xff0c;Mybatis会做特殊处理 1:传递多个多个参数时候&#xff0c;第一种写法如下 比如传递了两个参数&#xff0c;用 #{param1} and #{param2}取值 2:传递多个多个参数时候&#xff0c…

No.7 nginx、nfs、集群

安装并启动nginx服务 1、二进制安装nginx包 ~ yum -y install epel-release && yum -y install nginx #配置环境 关闭防火墙 ~ iptables -F // 或 systemctl stop filewallf 2、作为web服务修改配置文件 ~ vim /etc/nginx/nginx.conf //暂时不修改配置 3…

jsapi支付签名_微信支付小程序支付全流程

点击蓝色字关注我们&#xff01;一个努力中的公众号长的好看的人都关注了本文给大家讲解微信小程序支付全流程&#xff0c;以及相关功能源代码&#xff0c;项目不开放&#xff0c;带来不便尽请谅解。小程序支付主要包含如下几步骤&#xff0c;1.预下单-调用微信统一下单接口进行…

攻击防护手段_如何防护ddos流量攻击?

量攻击分很多种&#xff1a;我们常见的DDOS CC SYN UDP等&#xff0c;目前在网络中&#xff0c;流量攻击比较难解决&#xff0c;普通的IDC机房或是服务器商都是依靠硬防来解决&#xff0c;但是碰到大流量攻击&#xff0c;往往是拔线了事&#xff0c;所以都不是什么好办法&#…