Java线程安全问题

Java线程安全问题,第1张

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比较类似,看下面的 *** 作示意图即可

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

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5693576.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存