在局部变量上进行同步是否合理?

从Java内存模型中,我们知道每个线程都有自己的线程堆栈,并且局部变量被放置在每个线程自己的线程堆栈中。

并且其他线程无法访问这些局部变量。

那么,在哪种情况下,我们应该在局部变量上进行同步呢?


答案 1

您正在谈论以下情况:

public class MyClass {
    public void myMethod() {
        //Assume Customer is a Class
        Customer customer = getMyCustomer();
        synchronized(customer) {
            //only one thread at a time can access customer object
              which ever holds the lock
        }
    }
}

在上面的代码中,customer 是一个局部引用变量,但你仍在使用同步块来限制对对象所指向的访问(一次通过单个线程)。customer

在 Java 内存模型中,对象位于堆中(即使引用是位于堆栈中的线程的本地引用),而同步就是一次只限制一个线程对堆上对象的访问

简而言之,当你说局部变量(非基元)时,只有引用是局部的,而不是实际的对象本身,也就是说,它实际上指的是堆上的一个对象,这个对象可以被许多其他线程访问。因此,您需要对对象进行同步,以便单个线程一次只能访问该对象。


答案 2

有两种情况:

  1. 局部变量的基元类型类似于 或 。intdouble
  2. 局部变量的引用类型类似于 。ArrayList

在第一种情况下,您无法同步,因为您只能在对象(由引用类型变量指向)上进行同步。

在第二种情况下,这完全取决于局部变量指向的内容。如果它指向其他线程(也可以)指向的对象,则需要确保代码已正确同步。

示例:您从 或 实例字段中分配了局部变量,或者从共享集合中获取了对象。static

但是,如果对象是在线程中创建的,并且仅分配给该局部变量,并且您从未从线程向另一个线程提供对它的引用,并且对象实现本身也不提供引用,则无需担心同步。