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: 文章用于学习交流,如有错误之处,请大家指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值