并发操作之——多线程业务场景以及volatile关键字、指令重排、先行原则

并发操作

并发操作之——多线程业务场景



前言

并发操作之——多线程业务场景。


一、多线程的业务场景有哪些?

1、异步任务:

用户注册、记录日志

2、定时任务:

定期备份日志、备份数据库

3、分布式计算:

Hadoop处理任务mapreduce,master-wark(单机单进程)

4、服务器编程:

Socket网络编程,一个连接一个线程

ex:

短信云平台请求和数据库日志备份多线程

二、怎么理解volatile关键字以及volatile关键字和synchronized的区别?

volatile:

volatile是轻量级的synchronized,保证了共享变量的可见性,被volatile关键字修饰的变量,如果值发生了变化,其他线程立刻可见,避免出现脏读现象

volatile和synchronized的区别

volatile:保证可见性,但是不能保证原子性
synchronized:保证可见性,也保证原子性
使用场景
1、不能修饰写入操作依赖当前值的变量,比如num++、num=num+1,不是原子操作,肉眼看起来是,但是JVM字节码层面不止一步

2、由于禁止了指令重排,所以JVM相关的优化没了,效率会偏弱

为什么会出现脏读?

JAVA内存模型简称 JMM
JMM规定所有的变量存在在主内存,每个线程有自己的工作内存,线程对变量的操作都在工作内存中进行,不能直接对主内存就行操作

使用volatile修饰变量
每次读取前必须从主内存属性最新的值
每次写入需要立刻写到主内存中

volatile关键字修修饰的变量随时看到的自己的最新值,假如线程1对变量v进行修改,那么线程2是可以马上看见。
在这里插入图片描述

三、指令重排

指令重排序分两类 编译器重排序和运行时重排序

JVM在编译java代码或者CPU执行JVM字节码时,对现有的指令进行重新排序,主要目的是优化运行效率(不改变程序结果的前提)

int a = 3 //1
int b = 4 //2
int c =5 //3
int h = abc //4

定义顺序 1,2,3,4
计算顺序 1,3,2,4 和 2,1,3,4 结果都是一样


虽然指令重排序可以提高执行效率,但是多线程上可能会影响结果,有什么解决办法?

解决办法:

内存屏障

解释:

内存屏障是屏障指令,使CPU对屏障指令之前和之后的内存操作执行结果的一种约束

四、先行原则

先行发生原则,volatile的内存可见性就提现了该原则之一

例子:
//线程A操作
int k = 1;

//线程B操作
int j = k;

//线程C操作
int k = 2

分析:
假设线程A中的操作“k=1”先行发生于线程B的操作“j=k”,那确定在线程B的操作执行后,变量j的值一定等于1,依据有两个:一是先行发生原则,“k=1”的结果可以被观察到;二是第三者线程C还没出现,线程A操作结束之后没有其他线程会修改变量k的值。

但是考虑线程C出现了,保持线程A和线程B之间的先行发生关系,线程C出现在线程A和线程B的操作之间,但是线程C与线程B没有先行发生关系,那j的值会是多少?答案是1和2都有可能,因为线程C对变量k的影响可能会被线程B观察到,也可能不会,所以线程B就存在读取到不符合预期数据的风险,不具备多线程安全性

八大原则

1、程序次序规则
2、管程锁定规则
3、volatile变量规则
4、线程启动规则
5、线程中断规则
6、线程终止规则
7、对象终结规则
8、传递性


总结

并发编程基础知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RobertTeacher

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值