java static方法 引用static属性 存在线程安全问题-原理分析

java static方法 引用static属性 存在线程安全问题-原理分析

测试代码

package javabase.src.thread;


public class StaticMethodTest {

    private static int a = 0;

    public static void main(String[] args) {

        new Thread(StaticMethodTest::run, "thread1").start();


        new Thread(() -> run2(), "thread2").start();
    }


    public static void test(int param) throws InterruptedException {
        System.out.println("==============="+Thread.currentThread().getName()+"操作之前的a值:"+a+"===================");
        // 先让 线程进行操作之前 都能 先拿值(造成线程安全问题)
        Thread.sleep(1000);
        a += param;
        System.out.println("==============="+Thread.currentThread().getName()+"进行加"+param+"操作之后的a值:"+a+"=============");

    }

    private static void run() {
        try {
            test(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void run2() {
        try {
            // 目的 : 等待 其他线程执行完毕后在执行
            // 让执行此业务的 线程 先sleep 1秒 
            Thread.sleep(1000);
            test(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

===============thread1操作之前的a值:0===================
===============thread2操作之前的a值:0===================
===============thread1进行加1操作之后的a值:1=============
===============thread2进行加2操作之后的a值:3=============

结果分析:

通过结果我们很容易看出问题所在

​ thread1和thread2 进行运算之前获取的值都是 0

​ thread1:0 + 1 = 1 结果正确

​ thread2:0 + 2 = 3 结果错误

原理分析

​ static修饰的属性 在JVM 内存中是存储在 方法区中,全局使用的此属性 只有一份

public static void test(int param) throws InterruptedException {
    System.out.println("==============="+Thread.currentThread().getName()+"操作之前的a值:"+a+"===================");
    // 先让 线程进行操作之前 都能 先拿值(造成线程安全问题)
    Thread.sleep(1000);
    a += param;
    System.out.println("==============="+Thread.currentThread().getName()+"进行加"+param+"操作之后的a值:"+a+"=============");

}
  • thread1执行test(1)之后 现在 thread2方法栈中 a的值 也已经改变,
private static void run() {
    try {
        test(1);
        // 代码执行到此处时 a 的值 已经变成了 1
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

note: 文章用于学习交流,如有错误之处,请大家指正

发布了2 篇原创文章 · 获赞 0 · 访问量 126

猜你喜欢

转载自blog.csdn.net/qq_41692766/article/details/105512575
今日推荐