【揭秘】线程A为何无法访问线程B变量?

2024-01-07 22:42:03

【百家号水贴】【揭秘】线程A为何无法访问线程B变量? - 程序员古德

前两天一个开发同事问我,为什么线程A创建的变量在线程B读取不到?这个问题就设计到线程之间变量作用域的问题了。

在Java中,变量作用域通常指的是变量在代码中的可访问范围,如,方法内可见,类中可见和全局可见,如果一个变量在某个作用域内声明,那么只有在这个作用域内或者嵌套的作用域内才能访问这个变量。在多线程编程中,作用域问题可能导致一个线程无法访问另一个线程中定义的变量。

下面是一个的例子,演示了变量作用域问题如何影响多线程程序中的变量,如下代码:

public class ScopeExample {  
    public static void main(String[] args) {  
        Thread thread1 = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                int localVariableInThread1 = 42; // 线程1的局部变量  
                System.out.println("Thread 1: localVariableInThread1 = " + localVariableInThread1);  
            }  
        });  
  
        Thread thread2 = new Thread(() -> {  
            // 这里无法访问localVariableInThread1,因为它是在thread1的作用域内定义的  
            // 下面的代码会导致编译错误:  
            // int copiedValue = localVariableInThread1; // 错误:找不到符号  
            System.out.println("Thread 2 is running, but cannot access localVariableInThread1");  
        });  
  
        thread1.start();  
        thread2.start();  
    }  
}

在这个例子中,localVariableInThread1 是在 thread1run 方法内部定义的局部变量,由于它是局部变量,它的作用域仅限于 run 方法内部,因此,当 thread2 尝试访问 localVariableInThread1 时,它无法访问的,因为这个变量对 thread2 是不可见的。

要解决这个问题,可以使用类变量或者全局变量,例如,将其定义为类的字段(静态或非静态),这样所有的线程都可以访问它,如下代码:

public class SharedScopeExample {  
    private static int sharedVariable = 42; // 静态字段,对所有线程可见  
  
    public static void main(String[] args) {  
        Thread thread1 = new Thread(() -> {  
            System.out.println("Thread 1: sharedVariable = " + sharedVariable);  
            // 可以修改sharedVariable的值  
            sharedVariable = 99;  
        });  
  
        Thread thread2 = new Thread(() -> {  
            // 稍微延迟,以便thread1有机会修改sharedVariable的值  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            System.out.println("Thread 2: sharedVariable = " + sharedVariable); // 可以访问sharedVariable的值  
        });  
  
        thread1.start();  
        thread2.start();  
    }  
}

在这个修改后的例子中,sharedVariable 是一个静态字段,对所有线程都是可见的。因此,thread1thread2 都可以访问和修改它的值。

其它知识参考(来自网络CV),如下:

JMM,Java内存模型概念,它规定了内存主要划分为主内存和工作内存两种,主内存和工作内存与JVM内存划分(堆、栈、方法区)在不同的层次上,如果非要对应,主内存对应的是Java堆中的对象实例部分,工作内存对应的是栈中的部分区域,从更底层来说,主内存对应的是硬件的物理内存,工作内存对应的是寄存器和高速缓存。

此外,JMM还定义了线程和主内存之间的抽象关系,线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本,而且,JMM还规定所有的共享变量都存储于主内存,这里的共享变量指的是实例变量和类变量,不包含局部变量,因为局部变量是线程私有的,因此不存在竞争问题。

关注我,每天学习互联网编程技术 - 程序员古德

文章来源:https://blog.csdn.net/qusikao/article/details/135405737
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。