当前位置:首页 > 科技  > 软件

深入理解并发编程中的三个问题

来源: 责编: 时间:2024-03-19 17:35:13 131观看
导读1.可见性可见性(Visibility):是指一个线程对共享变量进行修改,另一个先立即得到修改后的最新值。1.1 可见性案例演示一个线程根据boolean类型的标记flag, while循环,另一个线程改变这个flag变量的值,另 一个线程并不会停止循

1.可见性

可见性(Visibility):是指一个线程对共享变量进行修改,另一个先立即得到修改后的最新值。42T28资讯网——每日最新资讯28at.com

1.1 可见性案例演示

一个线程根据boolean类型的标记flag, while循环,另一个线程改变这个flag变量的值,另 一个线程并不会停止循环。42T28资讯网——每日最新资讯28at.com

public class VisibilityTest {    // 多个线程都会访问的数据,我们称为线程的共享数据    // 定义一个静态的 boolean 变量 run,初始值为 true    private static boolean run = true;     public static void main(String[] args) throws InterruptedException {        // 创建并启动线程 t1        Thread t1 = new Thread(() -> {            // 在 run 变量为 true 时循环输出消息            while (run) {                System.out.println(Thread.currentThread().getName() + "线程1 run = " + run);            }            // 循环结束后输出最终消息            System.out.println(Thread.currentThread().getName() + "线程1 run = " + run);        });        t1.start(); // 启动线程 t1        Thread.sleep(1000); // 主线程睡眠1秒钟        // 创建并启动线程 t2        Thread t2 = new Thread(() -> {            run = false; // 将 run 变量设置为 false            System.out.println(Thread.currentThread().getName() + "时间到,线程2设置为false");        });        t2.start(); // 启动线程 t2    }}

输出结果:42T28资讯网——每日最新资讯28at.com

Thread-0线程1 run = trueThread-0线程1 run = true// .....结果省略Thread-1时间到,线程2设置为falseThread-0线程1 run = false

线程1开始运行时run=true,所以会不断循环输出Thread-0线程1 run = true,线程2运行后设置run=false,线程1发现run=true后就停止输出。42T28资讯网——每日最新资讯28at.com

总结:并发编程时,会出现可见性问题,当一个线程对共享变量进行了修改,另外的线程并没有立即看到修改后的最新值。42T28资讯网——每日最新资讯28at.com

2.原子性

原子性(Atomicity):在一次或多次操作中,要么所有的操作都执行并且不会受其他因素干扰而中断,要么所有的操作都不执行。42T28资讯网——每日最新资讯28at.com

2.1 可见性案例演示

5个线程各执行1000次 i++42T28资讯网——每日最新资讯28at.com

public class AtomicityTest {    private static int number = 0; // 定义一个静态的整数变量 number,初始值为 0    public static void main(String[] args) throws InterruptedException {        Runnable increment = () -> {            // 定义一个 Runnable 匿名类 increment,用于对 number 进行累加操作            for (int i = 0; i < 1000; i++) {                number++; // 对 number 进行累加操作            }        };        ArrayList<Thread> ts = new ArrayList<>(); // 创建一个 ArrayList 用于存储线程对象        for (int i = 0; i < 5; i++) {            Thread t = new Thread(increment); // 创建一个新线程,传入 increment Runnable 实例            t.start(); // 启动线程            ts.add(t); // 将线程对象添加到 ArrayList 中        }        for (Thread t : ts) {            t.join(); // 等待所有子线程执行完毕        }        System.out.println("number = " + number); // 输出最终的 number 值    }}

思考:最终number结果可能是多少?42T28资讯网——每日最新资讯28at.com

结果可能是5000,也可能是小于5000的结果都有可能。42T28资讯网——每日最新资讯28at.com

对于 number++ 而言(number 为静态变量),实际会产生如下的 JVM 字节码指令:42T28资讯网——每日最新资讯28at.com

9: getstatic #12 // Field number:I12: iconst_113: iadd14: putstatic #12 // Field number:I

可见number++是由多条语句组成,以上多条指令在一个线程的情况下是不会出问题的,但是在多线程情况下就可能会出现问题。比如一个线程在执行13: iadd时,另一个线程又执行9: getstatic。会导致两次number++,实际上只加了1。42T28资讯网——每日最新资讯28at.com

总结:并发编程时,会出现原子性问题,当一个线程对共享变量操作到一半时,另外的线程也有可能来操作共享变量,干扰了前一个线程的操作。42T28资讯网——每日最新资讯28at.com

3.有序性

有序性(Ordering):是指程序中代码的执行顺序,Java在编译时和运行时会对代码进行优化,会导致程序最终的执行顺序不一定就是我们编写代码时的顺序。42T28资讯网——每日最新资讯28at.com

3.1.  有序性可见性案例演示

有序性42T28资讯网——每日最新资讯28at.com

jcstress是Java并发压测工具。42T28资讯网——每日最新资讯28at.com

pom文件,添加依赖。42T28资讯网——每日最新资讯28at.com

<dependency>    <groupId>org.openjdk.jcstress</groupId>    <artifactId>jcstress-core</artifactId>    <version>0.5</version></dependency>

代码:42T28资讯网——每日最新资讯28at.com

@JCStressTest@Outcome(id = {"1", "4"}, expect = Expect.ACCEPTABLE, desc = "ok")@Outcome(id = "0", expect = Expect.ACCEPTABLE_INTERESTING, desc = "danger")@Statepublic class OrderingTest {   int num = 0;   boolean ready = false;   // 线程1执行的代码    @Actor   public void actor1(I_Result r) {       if (ready) {           r.r1 = num + num;       } else {           r.r1 = 1;       }   }   // 线程2执行的代码    @Actor   public void actor2(I_Result r) {       num = 2;       ready = true;   }}

I_Result 是一个对象,有一个属性 r1 用来保存结果。42T28资讯网——每日最新资讯28at.com

思考:在多线程情况下可能出现几种结果?42T28资讯网——每日最新资讯28at.com

  • 情况1:线程1先执行actor1,这时ready = false,所以进入else分支结果为1。
  • 情况2:线程2执行到actor2,执行了num = 2;和ready = true,线程1执行,这回进入 if 分支,结果为 4。
  • 情况3:线程2先执行actor2,只执行num = 2;但没来得及执行 ready = true,线程1执行,还是进入else分支,结果为1。

注意:还有第四种情况,结果为0。42T28资讯网——每日最新资讯28at.com

  • 情况4:线程2java编译后结果
ready = true;num = 2;

线程2先执行actor2,执行了ready = true,但没来得及执行执行num = 2,线程1执行,还是进入if分支,结果为0。42T28资讯网——每日最新资讯28at.com

42T28资讯网——每日最新资讯28at.com

运行测试:42T28资讯网——每日最新资讯28at.com

mvn clean installjava -jar target/jcstress.jar

部分jcstress测试结果,0结果出现1384次。42T28资讯网——每日最新资讯28at.com

42T28资讯网——每日最新资讯28at.com

完整pox.xml:42T28资讯网——每日最新资讯28at.com

<properties>        <maven.compiler.source>8</maven.compiler.source>        <maven.compiler.target>8</maven.compiler.target>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <javac.target>1.8</javac.target>        <uberjar.name>jcstress</uberjar.name>    </properties>    <dependencies>        <dependency>            <groupId>org.openjdk.jcstress</groupId>            <artifactId>jcstress-core</artifactId>            <version>0.5</version>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.1</version>                <configuration>                    <compilerVersion>${javac.target}</compilerVersion>                    <source>${javac.target}</source>                    <target>${javac.target}</target>                </configuration>            </plugin>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-shade-plugin</artifactId>                <version>2.2</version>                <executions>                    <execution>                        <id>main</id>                        <phase>package</phase>                        <goals>                            <goal>shade</goal>                        </goals>                        <configuration>                            <finalName>${uberjar.name}</finalName>                            <transformers>                                <transformer                                        implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">                                    <mainClass>org.openjdk.jcstress.Main</mainClass>                                </transformer>                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">                                    <resource>META-INF/TestList</resource>                                </transformer>                            </transformers>                        </configuration>                    </execution>                </executions>            </plugin>        </plugins>    </build>


42T28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-77831-0.html深入理解并发编程中的三个问题

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 在 Go 中如何停止程序

下一篇: 构建一个通用灵活的JavaScript插件系统?看完你也会!

标签:
  • 热门焦点
  • K60至尊版狂暴引擎2.0加持:超177万跑分斩获性能第一

    K60至尊版狂暴引擎2.0加持:超177万跑分斩获性能第一

    Redmi的后性能时代战略发布会今天下午如期举办,在本次发布会上,Redmi公布了多项关于和联发科的深度合作,以及新机K60 Ultra在软件和硬件方面的特性,例如:“K60 至尊版,双芯旗舰
  • 俄罗斯:将审查iPhone等外国公司设备 保数据安全

    俄罗斯:将审查iPhone等外国公司设备 保数据安全

    iPhone和特斯拉都属于在各自领域领头羊的品牌,推出的产品也也都是数一数二的,但对于一些国家而言,它们的产品可靠性和安全性还是在限制范围内。近日,俄罗斯联邦通信、信息技术
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • 三言两语说透柯里化和反柯里化

    三言两语说透柯里化和反柯里化

    JavaScript中的柯里化(Currying)和反柯里化(Uncurrying)是两种很有用的技术,可以帮助我们写出更加优雅、泛用的函数。本文将首先介绍柯里化和反柯里化的概念、实现原理和应用
  • 微信语音大揭秘:为什么禁止转发?

    微信语音大揭秘:为什么禁止转发?

    大家好,我是你们的小米。今天,我要和大家聊一个有趣的话题:为什么微信语音不可以转发?这是一个我们经常在日常使用中遇到的问题,也是一个让很多人好奇的问题。让我们一起来揭开这
  • 只需五步,使用start.spring.io快速入门Spring编程

    只需五步,使用start.spring.io快速入门Spring编程

    步骤1打开https://start.spring.io/,按照屏幕截图中的内容创建项目,添加 Spring Web 依赖项,并单击“生成”按钮下载 .zip 文件,为下一步做准备。请在进入步骤2之前进行解压。图
  • 使用AIGC工具提升安全工作效率

    使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 共享单车的故事讲到哪了?

    共享单车的故事讲到哪了?

    来源丨海克财经与共享充电宝相差不多,共享单车已很久没有被国内热点新闻关照到了。除了一再涨价和用户直呼用不起了。近日多家媒体再发报道称,成都、天津、郑州等地多个共享单
  • 三星Galaxy Z Fold/Flip 5国行售价曝光 :最低7499元/12999元起

    三星Galaxy Z Fold/Flip 5国行售价曝光 :最低7499元/12999元起

    据官方此前宣布,三星将于7月26日也就是明天在韩国首尔举办Unpacked活动,届时将带来带来包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
Top