栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java线程安全问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java线程安全问题

多线程安全问题:

cpu调度每一个线程,分配线程时间片的时候,该线程才会被执行,由于分时操作,当发生指令交错的时候,就会引起线程安全问题。

一个程序运行多个线程是没有问题的,问题出现与多个线程访问共享资源,对共享资源读写操作时,就容易出现问题。举一个例子,下面的代码中,main方法中定义了两个线程,线程t1对counter变量进行5000加操作,t2线程对counter变量进行了5000次减操作。启动两个线程,等到两个线程运行结束之后,counter变量会是多少呢?答案是正数、负数、0都有可能。因为两个线程都对counter变量进行操作,当发生指令交错,最终的结果是未知的。

    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();
        System.out.println(counter);
    }

看下面的情况,两个线程对主内存中的i变量分别进行自增和自减,刚才说过会出现三种情况,我们来看一下三种情况对应的底层指令是如何进行的。


  •  情况1:结果为0

这种情况非常简单,线程1将i取出,对i自增,再将i放入到内存中,操作完之后,线程2将i取出,i自减,再将i放回,只要每个线程将i取出,并对i放回之间,不被其他线程打扰,换句话说,一个县城对i操作的过程中,不被其他线程打扰,i最终的值都是0。

重点的结果不为0的情况,也就是一个线程对i操作时,被其他线程打断了(指令交错)。


  • 情况2:结果为正数

 刚开始i为0,线程2将i取出,进行自减,i变为-1,还没有将i放入到主内存中,cpu说,你的时间片用完了,保存你现在的状态,准备走吧,线程2将i = -1记下,并将程序计数器指向下一行将要操作的指令(将i放入到主内存中)。

线程1获得时间片,开始执行,由于线程2还没有将i的值更新,因此此时i依然为0,将i从主内存中取出,i自增变为1,再将i = 1更新到主内中,此时i 变为1。

线程2再次获得了时间片,拿到时间片之后,线程2回复原来的状态(i = -1),然后开始执行程序计数器指向的指令,将i = -1 更新到主内存中,最终i = -1。


  • 情况3:结果为正数 

和情况2比较类似,看下面的操作示意图即可

 第一次发文,如果对你有帮助,希望给我一个小赞赞。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/693110.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号