Java多线程调用静态B对象方法后a属性值为何不是1?
class B { int a = 0; void method1() { // code a = a + 1; } } public class A extends Thread { static B obj1; public void run(){ obj1.method1(); } public static void main(String args[]){ obj1 = new B(); A a1 = new A(); a1.start(); A a2 = new A(); a2.start(); } }
静态引用obj1的工作机制
Java中被static修饰的成员属于类本身,不与类的实例绑定,整个程序运行期间全类共享同一份存储。
代码中A类的static B obj1是A类的静态成员,仅在A类加载时完成一次初始化,不管创建多少个A类的实例(比如代码中的a1、a2两个线程实例),所有实例访问的都是同一个obj1引用。
你在main方法中仅执行了一次obj1 = new B(),所以a1、a2两个线程执行run()方法中的obj1.method1()时,操作的是同一个B类对象,不存在每个线程持有独立B对象的情况。
你认为B类a属性值为1的认知疏漏
主要存在两个层面的错误:
- 对
static修饰符的作用认知偏差:你默认认为不同的A线程实例会持有各自独立的B类对象,按这个逻辑每个线程只会给各自持有的B对象的a属性加1,结果才会是1。但实际上两个线程操作的是同一个B对象的a属性,如果两个线程的method1完全串行执行,a的结果应该是2,而非1。 - 忽略了多线程环境下的竞态条件:
a = a + 1不是原子操作,执行时会被拆分为3个独立步骤:读取a的当前值、计算a+1的结果、将新值写回a。两个线程同时执行这段逻辑时可能出现指令交错:比如线程1读取到a=0,还没来得及将加1后的结果写回,线程2也读取到a=0,两个线程都计算出结果1再依次写回,最终a的结果就会是1。但这种情况是随机出现的,不是必然结果,这段代码运行后a的值可能是1也可能是2,没有固定的预期结果。
内容的提问来源于stack exchange,提问作者Shiny
相关产品推荐
相关产品推荐

