.class 的 Java 同步块
Posted
技术标签:
【中文标题】.class 的 Java 同步块【英文标题】:Java Synchronized Block for .class 【发布时间】:2011-01-04 14:27:27 【问题描述】:这段java代码是什么意思?它会锁定MyClass
的所有对象吗?
synchronized(MyClass.class)
//is all objects of MyClass are thread-safe now ??
上面的代码和这个有什么不同:
synchronized(this)
//is all objects of MyClass are thread-safe now ??
【问题讨论】:
相关:***.com/questions/437620/… 【参考方案1】:sn-p synchronized(X.class)
使用类实例作为监视器。由于只有一个类实例(在运行时表示类元数据的对象),因此该块中可以有一个线程。
synchronized(this)
块由实例保护。对于每个实例,只有一个线程可以进入块。
synchronized(X.class)
用于确保块中只有一个线程。 synchronized(this)
确保每个实例只有一个线程。如果这使得块中的实际代码线程安全取决于实现。如果只改变实例synchronized(this)
的状态就足够了。
【讨论】:
“有多少实例就有多少线程可以进入块”意味着第二种形式充当信号量,这是不正确的。你应该这样说:“同步(this)确保只有一个线程可以进入给定类实例的块”。 已更正。我是想这么说的。 类实例与实例是什么? 所以,如果你有一个静态方法并且我们不想同步它的所有主体,那么我们 synchronized(this) 不好,而是 synchronized(Foo.class) 是合适的。对吗?synchronized(X.class) is used to make sure that there is exactly one Thread in the block.
这是错误的,这取决于你有多少类加载器【参考方案2】:
添加到其他答案:
static void myMethod()
synchronized(MyClass.class)
//code
等价于
static synchronized void myMethod()
//code
和
void myMethod()
synchronized(this)
//code
等价于
synchronized void myMethod()
//code
【讨论】:
我读了第二遍才发现前两个例子有关键字“static”。只是向可能已经看到并错过它的其他人指出这一点。如果没有 static 关键字,前两个示例将不一样。 这些例子并不等同!当线程尝试调用方法时,同步方法被“同步”为一个漏洞。另一方面,这些块可以在它们上面和下面有代码,可以从多个线程中执行。它们只在块内同步!那不一样! public static Singleton getInstance() if (instance == null) synchronized (Singleton.class) instance = new Singleton(); 返回实例; 重点是在synchronized
块之外没有代码。这使它们等效。如果你换一个例子,它们确实不再一样了。
只需添加 synchronized(MyClass.class) 也可以从其他类中使用,而不仅仅是在 MyClass 中使用。我有一个遗留代码,其中几个类使用一个类的方法(比如说 Foo.saveStuff)。我需要确保一次只有一个线程使用 saveStuff。由于糟糕的数据库事务设计,我不能只使 safeStuff 同步,所以我必须在所有其他方法中使用 synchronized(Foo.class)。【参考方案3】:
不,第一个将锁定MyClass
的类定义,而不是它的所有实例。但是,如果在一个实例中使用,这将有效地阻止所有其他实例,因为它们共享一个类定义。
第二个将只锁定当前实例。
至于这是否使您的对象线程安全,这是一个复杂得多的问题 - 我们需要查看您的代码!
【讨论】:
是的,MyClass.class 可以是任何静态变量并且具有相同的效果。【参考方案4】:是的,它会(在任何同步块/功能上)。
我为自己想了几天这个问题(实际上是在 kotlin 中)。终于找到了很好的解释,想分享一下:
类级锁可防止多个线程在运行时进入类的所有可用实例中的同步块。这意味着如果在运行时有 100 个 DemoClass 实例,那么一次只有一个线程能够在任何一个实例中执行 demoMethod(),而所有其他实例都将被其他线程锁定。
应始终进行类级锁定以确保静态数据线程安全。我们知道 static 关键字将方法的数据与类级别相关联,因此在静态字段或方法上使用锁定使其在类级别。
还要注意为什么 .class。只是因为.class
等价于类的任何静态变量,类似于:
private final static Object lock = new Object();
其中锁变量名称为class,类型为Class
阅读更多: https://howtodoinjava.com/java/multi-threading/object-vs-class-level-locking/
【讨论】:
这不是真的,是的,它会阻止来自同一个类加载器的所有实例!以上是关于.class 的 Java 同步块的主要内容,如果未能解决你的问题,请参考以下文章
深入理解Java中的同步静态方法和synchronized(class)代码块的类锁