参数传递给synchronized的意义是什么?
synchronized ( parameter )
{
}
实现块级同步。在某处,我看到了像
这样的代码class test
{
public static final int lock =1;
...
synchronized(lock){
...
}
}
我不明白这段代码的目的。
任何人都可以给我一个更好的例子和/或解释它吗?
答案 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关键字(锁定执行类对象的实例)的原因是他们可能想要更精细或不同的东西等待锁定,这取决于他们的多线程如何算法设计。