块级同步

时间:2009-05-17 18:35:27

标签: java synchronization

参数传递给synchronized的意义是什么?

synchronized ( parameter )
{

}

实现块级同步。在某处,我看到了像

这样的代码
class test
{
    public static final int lock =1;

    ...

    synchronized(lock){
       ...
    }
}

我不明白这段代码的目的。

任何人都可以给我一个更好的例子和/或解释它吗?

5 个答案:

答案 0 :(得分:12)

这是锁定的参考。基本上两个线程不会同时执行使用相同引用同步的代码块。正如Cletus所说,同步的方法大致相当于在方法中使用synchronized (this)

我非常希望您看到的示例代码不像那样 - 您正在尝试在原始变量上进行同步。同步仅适用于监视器(通过引用) - 即使合法代码,x也会被装箱,这会导致一些非常奇怪的行为,因为有些整数总是被装箱到相同的引用,而其他整数将在每次打包时创建一个新对象。幸运的是,Java编译器意识到这是一个非常糟糕的主意,并且会为您发布的代码提供编译时错误。

更合理的代码是:

class Test
{
    private static final Object lock = new Object();

    ...

    synchronized(lock){
       ...
    }
}

我已将锁定为私有,并将其类型更改为Object。它是否应该是静态的取决于具体情况 - 如果你想从多个线程访问/更改静态数据,通常会使用静态变量;当您想要从多个线程访问/更改每个实例数据时,实例变量通常用于锁。

答案 1 :(得分:7)

此:

public synchronized void blah() {
  // do stuff
}

在语义上等同于:

public void blah() {
  synchronized (this) {
    // do stuff
  }
}

有些人不喜欢使用'this'进行同步,部分原因是它是公开的(因为实例对外部代码是可见的)。这就是为什么你最终会找到使用私人锁的人:

public class Foo
  private final static String LOCK = new String("LOCK");

  public void blah() {
    synchronized (LOCK) {
      // do stuff
    }
  }
}

好处是LOCK在类外是不可见的,你可以创建几个锁来处理更精细的锁定情况。

答案 2 :(得分:2)

synchronized语句(ref:here)的目的是确保在多线程应用程序中,只有一个线程可以在给定时间访问关键数据结构。

例如,如果让两个线程同时更改相同的数据结构,数据结构将被破坏,那么通常用锁来保护它。

在现实世界中,考虑一个公共厕所有钥匙的模拟器,悬挂在中央位置。在你可以使用厕所之前,你需要钥匙,不仅要进入,而且还要保证没有其他人会同时进入同一个厕所。他们将不得不等待密钥可用。

这就是这种锁构造的工作原理。

在这种情况下,synchronized关键字的参数是关键。您锁定密钥,执行您需要执行的操作,然后解锁密钥以允许其他人访问密钥。如果其他线程在当前被另一个线程锁定时尝试锁定该键,则该线程将不得不等待。

答案 3 :(得分:2)

我无法解释它因为它没有编译。你无法锁定基元。

另一个不好的例子是将其改为

public static final Integer lock =1;

这是一个坏主意,因为小的自动盒式基元被缓存,并且可能会产生奇怪的副作用(如果这样做不止一次)

答案 4 :(得分:1)

传递给synchronized的对象实例是“锁定单元”。其他执行尝试获取同一实例锁定的线程都将轮流等待。

人们使用它而不是方法级别synchronized关键字(锁定执行类对象的实例)的原因是他们可能想要更精细或不同的东西等待锁定,这取决于他们的多线程如何算法设计。