首页 > 其他分享 >i++在多线程下的原子性问题

i++在多线程下的原子性问题

时间:2023-01-31 23:23:47浏览次数:76  
标签:操作数 Thread 压入 ++ 原子 静态 多线程 变量

 

    static int i = 0;
    @Test
    void iTest() throws InterruptedException {
        Thread t1 = new Thread(()->{
            for (int j = 0; j < 50000; j++) {
                i++;
            }
        });

        Thread t2 = new Thread(()->{
            for (int j = 0; j < 50000; j++) {
                i--;
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();
        System.out.println(i);
    }

以上代码的结果可能为正数,负数或零,原因是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

在并发情况下,以上八行代码会乱序,导致结果不一定为0,可以在for循环外加上synchronized锁,结果就一定为0了。

标签:操作数,Thread,压入,++,原子,静态,多线程,变量
From: https://www.cnblogs.com/tyleaf/p/17081147.html

相关文章

  • CUDA C++ / 错误处理
    错误处理接收错误信息定义一个cudaError_t类型的变量来接收错误信息cudaError_terr;获取错误信息的字符串cudaGetErrorString(err);使用方法:cout<<cudaGetErrorStr......
  • [Python] 爬虫系统与数据处理实战 Part.3 多线程和分布式
    为什么用快反爬虫 多线程复杂性资源、数据的安全性:锁保护原子性:数据操作是天然互斥的同步等待:wait()、notify()、notifyall()死锁:多个线程对资源互锁容灾:任......
  • C++ 图进阶系列之 kruskal 和 Prim 算法_图向最小生成树的华丽转身
    1.前言树和图形状相似,也有差异性。树中添加一条或多条边,可成图。图中减小一条或多条边,可成树。形态的变化由数据之间的逻辑关系决定。图用来描述数据之间多对多关系。......
  • OpenHarmony stage worker 多线程
    作者:徐金生OpenHarmony存在一个与主线程并行的独立线程--Worker。对于处理耗时操作且不阻塞主线程起到了重要的作用,并且多个线程并发可以提高CPU和内存的利用率。在实际开......
  • 【八大数据排序法】冒泡排序法的图形理解和案例实现 | C++
    第十四章冒泡排序法:::hljs-center目录第十四章冒泡排序法●前言●认识排序●一、冒泡排序是什么?1.简要介绍2.具体情况3.算法分析●二、案例实现1.案......
  • 【c++】R-K法求解常微分方程
    最常用:四阶龙格库塔方法    例:  #include<iostream>#include<fstream>#include<cstring>doublefunc(double......
  • 多线程--消费者与生产者实例
    多线程实例1.消费者与生产者实例(管程法)产品、消费者、生产者、缓冲区产品,保证有一个唯一标识即可消费者继承Thread,注册缓冲区,从缓冲区消费生产者继承Thread,注册缓冲......
  • c++对文件的写入和读取操作
     写文件#include<iostream>usingnamespacestd;#include<fstream>voidtest01(){//1、包含头文件 //2、创建流对象 ofstreamofs;//3、指定打开方式 ofs.open("tes......
  • vscode 开发c++
     makefile.mk#makefile.mk公共头文件ifndefTARGET#/root/make/src/test_include#notdirTARGET:=$(notdir$(shellpwd))#test_includeendifCXXFLAGS:=$(CX......
  • 【c++】多项式曲线拟合
    源代码,截取至数值分析期末大作业。其中一步为多项式曲线拟合,求解出符合拟合精度的函数表达式。拟合和插值的区别?1.拟合:不必经过所有点2.插值:必须经过所有点(1)曲......