当前位置:网站首页>JUC(五):共享带来的问题
JUC(五):共享带来的问题
2022-07-30 02:45:00 【打工仔呀~】
Java代码示例
两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?
static int counter = 0;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
counter++;
}
}, "t1");
Thread t2 = new Thread(() -> {
for (int i = 0; i < 5000; i++) {
counter--;
}
}, "t2");
t1.start();
t2.start();
t1.join();
t2.join();
log.debug("{}",counter);
}
问题分析
以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增,自减并不是原子操作,要彻底理解,必须从字节码来进行分析
例如对于 i++ 而言(i 为静态变量),实际会产生如下的 JVM 字节码指令:
getstatic i // 获取静态变量i的值
iconst_1 // 准备常量1
iadd // 自增
putstatic i // 将修改后的值存入静态变量i
而对应 i-- 也是类似:
getstatic i // 获取静态变量i的值
iconst_1 // 准备常量1
isub // 自减
putstatic i // 将修改后的值存入静态变量i
而 Java 的内存模型如下,完成静态变量的自增,自减需要在主存和工作内存中进行数据交换:
如果是单线程以上 8 行代码是顺序执行(不会交错)没有问题:
但多线程下这 8 行代码可能交错运行: 出现负数的情况:
出现正数的情况:
临界区 Critical Section
一个程序运行多个线程本身是没有问题的
问题出在多个线程访问共享资源
多个线程读共享资源其实也没有问题
在多个线程对共享资源读写操作时发生指令交错,就会出现问题
一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区
static int counter = 0;
static void increment()
// 临界区
{
counter++;
}
static void decrement()
// 临界区
{
counter--;
}
竞态条件 Race Condition
多个线程在临界区内执行,由于代码的执行序列(字节码)不同而导致结果无法预测,称之为发生了竞态条件
边栏推荐
猜你喜欢
随机推荐
动态绑定href url
解决:Error while adding the mapper ‘interface to configuration. Error parsing Mapper XML
有一个设计时钟的题目,进行详细分析(三)
Not enough information to list load addresses in the image map. (STM32 compilation error)
重写并自定义依赖的原生的Bean方法
五种绑定彻底弄懂this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解
AI落地难?云原生助力企业快速应用机器学习 MLOps
新手入门上位机开发 C#语言:PC串口发送数据
Detailed explanation of carousel picture 2 - carousel pictures through left positioning
Not enough information to list load addresses in the image map.(STM32编译报错)
再度入围|“国产化”大潮来袭,汉得助力乘风破浪!
解决:npm ERR code ELIFECYCLE npm ERR errno 1(安装脚手架过程中,在npm run dev 时发生错误)
Leetcode.19 删链表倒数第 N 个结点(栈/先后指针)
绘制概率密度图
Houdini 地形知识点
STM32L4R9ZIY6PTR STM32L4 high-performance embedded-MCU
go grpc 自定义拦截器
【ModelArts系列】华为ModelArts训练yolov3模型(训练管理)
binary search tree
The display and hiding of widgets for flutter learning









