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

Is it reasonable to synchronize on a local variable?

从Java内存模型得知,每个线程都有自己的线程栈,局部变量放在每个线程自己的线程栈中。

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

那么在什么情况下我们应该同步局部变量?

重点是:同步是有目的的。您使用它来确保恰好 一个线程可以在任何给定时间执行一些特殊的值得保护的activity。

因此:如果您需要同步,它总是比一个线程。当然,然后您需要锁定 所有 这些线程可以访问的内容。

或者换句话说:锁门以防止你自己进入大楼是没有意义的。

但是,正如另一个答案所指出的:它实际上取决于 "local" 变量的定义。假设您有:

void foo() {
  final Object lock = new Object();
  Thread a = new Thread() { uses lock
  Thread b = new Thread() { uses lock

那么可以肯定的是,"local" 变量可以用作这两个线程的锁。除此之外:该示例之所以有效,是因为同步发生在特定对象的 monitor 上。对象驻留在堆上。全部。

是的,当局部变量用于同步访问来自线程的代码块时,它确实有意义,这些线程是在与局部变量相同的方法中定义和创建的。

有两种情况:

  1. 局部变量是原始类型,如intdouble
  2. 局部变量是引用类型,如ArrayList

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

第二种情况,全看局部变量指向什么。如果它指向其他线程(也可以)也指向的对象,那么您需要确保您的代码已正确同步。

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

但是,如果该对象是在您的线程中创建的,并且只分配给该局部变量,并且您从不将对它的引用从您的线程提供给另一个线程,并且对象实现本身也没有提供out 引用,那么你就不用担心同步问题了。

您说的是以下案例:

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 内存模型中,对象存在于堆中(即使引用对于存在于堆栈中的线程而言是本地的)并且同步就是限制对对象的访问heap 一次恰好一个线程。

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