【问题标题】:Is it reasonable to synchronize on a local variable?在局部变量上同步是否合理?
【发布时间】:2017-03-31 07:30:57
【问题描述】:

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

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

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

【问题讨论】:

  • 同步是在对象上,而不是在变量上。这个问题没有意义。
  • @shmosel 好点;我决定根据您的意见改写我的答案;-)

标签: java multithreading synchronization local-variables


【解决方案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 内存模型中,对象存在于堆中(即使引用对于存在于堆栈中的线程而言是本地的),同步就是将对堆上对象的访问限制为 1 个一次线程。

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

【讨论】:

  • 这个解释我不是很清楚。比如说,调用 getMyCustomer() 每次都会创建并返回 new Customer()。现在引用“客户”将指向内存中的不同对象,而每个线程都调用方法 myMethod()。在这种情况下,我们是否使同步块线程中的代码安全?
  • @SubrataNath getter 方法通常不会创建要返回的新对象。
【解决方案2】:

有两种情况:

  1. 局部变量属于基本类型,如intdouble
  2. 局部变量的引用类型类似于ArrayList

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

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

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

但是,如果对象是在您的线程中创建的,并且仅分配给该局部变量,并且您永远不会从线程向另一个线程发出对它的引用,并且对象实现本身也不会发出引用,那么你就不用担心同步了。

【讨论】:

    【解决方案3】:

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

    因此:如果您需要同步,则总是需要更多而不是一个线程。当然,您需要锁定那些所有这些线程都可以访问的东西。

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

    但是,正如另一个答案指出的那样:它实际上取决于“本地”变量的定义。假设你有:

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 我会因为容易出错和清晰度问题而避免这种情况。好吧,无论如何我都会避免synchronized 在这个时代。
      • 绝对是@Kayaman。唯一的问题不在于这样一个代码的有效性,而是让这样一个结构做有意义的工作的可能性。我可以想象代码生成器会吐出这样的源代码。
      猜你喜欢
      • 2014-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多