【问题标题】:What is the difference between synchronized methods and blocks?同步方法和块有什么区别?
【发布时间】:2010-04-28 09:43:41
【问题描述】:

synchronized方法synchronized语句有什么区别?

如果可能,请用一个例子来说明清楚。

【问题讨论】:

标签: java multithreading concurrency synchronization


【解决方案1】:

同步方法会锁定与类(即“this”)或类(如果是静态方法)的实例关联的监视器,并阻止其他人这样做,直到从该方法返回。同步块可以锁定任何监视器(您告诉它哪个),并且可以具有小于 encolsing 方法的范围。

如果同步块最终不等同于方法的整个范围和/或如果它们锁定的东西比实例(或静态的类)不那么严格,则首选同步块。

【讨论】:

    【解决方案2】:

    JLS 引述(包括示例):

    JLS 14.19 The synchronized Statement

    synchronized 语句代表正在执行的线程获取互斥锁,执行一个块,然后释放锁。当执行线程拥有锁时,没有其他线程可以获取锁。

    JLS 8.4.3.6 synchronized Methods

    synchronized 方法在执行之前获取监视器。对于类 (static) 方法,使用与方法类的 Class 对象关联的监视器。对于实例方法,使用与this(调用该方法的对象)关联的监视器。

    这些与synchronized 语句可以使用的锁相同;因此,代码:

    class Test {
        int count;
        synchronized void bump() { count++; }
        static int classCount;
        static synchronized void classBump() {
            classCount++;
        }
    }
    

    效果完全一样:

    class BumpTest {
        int count;
        void bump() {
            synchronized (this) {
                count++;
            }
        }
        static int classCount;
        static void classBump() {
            try {
                synchronized (Class.forName("BumpTest")) {
                    classCount++;
                }
            } catch (ClassNotFoundException e) {
                    ...
            }
        }
    }
    

    那么它们有何不同?

    引用Effective Java 2nd Edition,第 67 条:避免过度同步:

    作为一项规则,您应该在synchronized 区域内做尽可能少的工作。

    方法的synchronized 修饰符是一种语法糖,适用于许多但并非所有场景。这本书更详细地讨论了为什么你应该避免过度同步,但基本上通过使用synchronized 语句,你可以更好地控制synchronized 区域的边界(如果场景需要,你也可以选择你自己的锁)。

    除非您的方法非常简单和/或您需要在方法的整个持续时间内获取this 锁(或者如果方法是static,则需要Class 对象锁),您应该使用@987654340 @ 语句将方法内的同步限制为仅在您需要时(即当您访问共享的可变数据时)。

    【讨论】:

      【解决方案3】:

      synchronized 方法是其主体自动封装在 synchronized 块中的方法。

      因此,这是相等的:

      public void foo()
      {
          synchronized (this)
          {
              bar();
          }
      }
      
      public synchronized void foo()
      {
          bar();
      }
      

      【讨论】:

        【解决方案4】:

        synchronized on 方法被锁定在 this 对象上。等于synchronized (this) {}

        标准synchronized 被锁定在指定的对象/监视器上。使用synchronized (***) {},您可以选择用于锁定的对象。

        【讨论】:

          【解决方案5】:

          同步方法实际上是将函数的整个主体放在同步块中。同步块的优点是您可以将同步块应用于函数中的几个选择语句,而不是整个函数。通常,最好使同步块尽可能短,因为在同步块中花费的时间可能会阻止其他线程执行有意义的工作。另一个区别是,您可以在使用同步块时指定要对其应用锁的特定对象,而使用同步方法时,对象本身会自动用作执行同步的锁。

          【讨论】:

            猜你喜欢
            • 2011-05-22
            • 2010-11-12
            • 2012-01-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-10
            • 1970-01-01
            • 2011-01-09
            相关资源
            最近更新 更多