我在某处读到various reasons应该避免synchronized(this)
。然而,我遇到的一些可敬的代码在构造函数中使用以下代码:
public SomeClass(Context context) {
if (double_checked_lock == null) {
synchronized (SomeClass.class) {
if (double_checked_lock == null) {
// some code here
}
}
}
}
synchronized(this)
和synchronized(SomeClass.class)
之间真的有区别吗?
答案 0 :(得分:26)
synchronized(this)
在当前对象上同步,因此只有一个线程可以访问每个实例,但不同的线程可以访问不同的实例。例如。每个线程可以有一个实例。
这通常有助于防止多个线程同时更新对象,这可能会造成不一致的状态。
synchronized(SomeClass.class)
在当前对象的类上同步(或者如果有人希望的话,则为另一个类),因此一次只有一个线程可以访问任何实例那个班。
这可能用于保护在类的所有实例(实例缓存或实例总数的计数器)之间共享的数据不会进入不一致状态。
答案 1 :(得分:6)
this
都不同
ClassName.class
不是。
因此,synchronized(this)
将允许多个实例同时运行。
答案 2 :(得分:3)
synchronized
关键字,当应用于类的class
锁时,以及它应用于当前对象实例上的this
锁时。从Java语言规范,8.4.3.6, 'synchronized Methods'部分:
synchronized方法在执行之前获取监视器(第17.1节)。对于类(静态)方法,使用与方法类的Class对象关联的监视器。对于实例方法,使用与此关联的监视器(调用该方法的对象)。
答案 3 :(得分:2)
每个java Object都可以拥有一个锁。这个锁一次最多可以保存一个线程,任何其他线程都必须等待获取同一个对象的锁。
synchronized(this)
获取当前线程的实例this
的锁定。该方法可以在不同的实例上并行运行(不同的值,因此不同的锁)
synchronized(SomeClass.class)
获取SomeClass的全局类对象的锁。只有一个方法实例可以运行,因为所有对象实例都锁定在同一个全局对象上(相同的锁)。
答案 4 :(得分:1)
这是要锁定的2个不同对象: 'this'指的是当前实例上下文,因此,例如,如果每个线程使用不同的实例并锁定它,则创建多个实例将不起作用。 'this'只能在非静态环境中引用 'class'是Java Class的静态成员,它只有一个实例。您可以在静态和非静态环境中锁定它。
答案 5 :(得分:1)
synchronized(this)
在对象的实例上进行同步。
synchronized(SomeClass.class)
使用表示SomeClass的Class对象的实例,它对同一类加载器中的所有实例都是全局的。
因此,这些是具有不同语义的不同结构。
单独使用synchronized
或作为方法修饰符,还可以在实例的信号量上进行同步,信号量通常用于防止多个线程之间的争用作为共享资源(即List)访问该实例。
您引用的线程声明使用私有实例是一种更好的做法,因为直接在对象实例上进行同步可能会很危险。为此你可以使用:
class MySharedResourceClass {
private SomeClass lock = new SomeClass();
public doSomething() {
synchronized (lock) {
// Do something here
}
}
}