为了账号安全,请及时绑定邮箱和手机立即绑定

混淆Java同步方法、synchronized(this)和synchronized类

混淆Java同步方法、synchronized(this)和synchronized类

MMMHUHU 2021-08-25 16:31:14
由于 Java 的同步概念,我很困惑。让我们假设以下类:class MyClass {  public synchronized void foo() { //do something }  public void bar() {    synchronized(this) { //do something }  }  public void normal() { //do something }}据我所知,foo和bar方法的工作原理相同。但是,在线程A进入bar方法并通过 同步实例后synchronized(this),任何线程都可以调用正常方法吗?据我所知,有些线程不管调用方法都可以调用普通foo方法。但我不确定何时bar调用该方法,因为它同步了一个实例。另外,让我们假设以下方法:class StaticMyClass {  public static synchronized void fooStatic() { //do something }  publi static void barStatic() {    synchronized(StaticMyClass.class) { //do something }  }  public static void normalStatic() { //do something }}在这里,有同样的问题。线程 A 进入临界区后,即synchronized(StaticMyClass.class)或fooStatic方法,任何线程都可以调用normalStatic?我认为,fooStatic和normalStatic可以独立调用,但barStatic并normalStatic不能。如果错了,为什么?我感谢您的帮助。
查看完整描述

3 回答

?
慕丝7291255

TA贡献1859条经验 获得超6个赞

据我所知,foobar方法的工作一样。

正确。它们都在 上同步this

线程 A 进入bar方法并通过 同步实例后synchronized(this),任何线程都可以调用normal方法吗?

是的。正确的。

据我所知,normal无论调用foo方法,某些线程都可以调用方法。但我不确定何时调用 bar 方法。因为它同步了一个实例。

foo并且bar是一样的。它们都在 上同步this。该normal方法不同步任何东西。因此,它可以随时从任何地方调用,并且不会在方法调用时或内部阻塞。

在您的术语中,该normal方法不是关键部分1


静态的第二个例子

在这里,有同样的问题。线程 A 进入临界区后,任何线程都可以调用synchronized(StaticMyClass.class)fooStatic方法normalStatic吗?

是的。在fooStaticbarStatic上都能够同步StaticMyClass.class

我认为,呼叫fooStaticnormalStatic可以独立调用,但barStaticnormalStatic不能。

不正确。在normalStatic不被挡fooStaticOR barStatic

我不确定你从哪里得到normalStatic可能被阻塞的想法......但它是一个正常的方法调用并且不获取任何内在锁,所以它不能被锁阻塞。


你的第三个例子不清楚。代码显示了一件事,但问题提出了不同/不相关的问题。


1 - 如果(例如)foo或在持有内在锁时bar调用它可能会有点混乱normal。然后normal代码将有效地位于临界区,因为调用者持有锁。但它 ( normal) 通常不会知道这一点。这就是为什么我更喜欢避免使用“临界区”术语的原因。


查看完整回答
反对 回复 2021-08-25
?
不负相思意

TA贡献1777条经验 获得超10个赞

如果您没有指定谁是监视器,那么对于实例方法,监视器就是实例(this),对于静态方法,监视器就是类(YourClass.class)。

这段代码

public synchronized void foo() { //do something }

和这个一样

public void foo() {   synchronized(this) { //do something }}

和这段代码

public static synchronized void fooStatic() { //do something }

和这个一样

public static void fooStatic() {
   synchronized(StaticMyClass.class) { //do something }
   }

所以,在这两种情况下,foo 和 bar 都是依赖的(同时只有一个线程),而 normal 可以独立调用。


查看完整回答
反对 回复 2021-08-25
?
largeQ

TA贡献2039条经验 获得超7个赞

但是线程A进入bar方法并通过synchronized(this)同步实例后,任何线程都可以调用正常的方法吗?

对同一对象的同步方法的两次调用不可能交错。当一个线程正在为一个对象执行同步方法时,所有其他调用同一个对象的同步方法的线程都会阻塞(挂起执行),直到第一个线程完成对对象的处理。

如果您尝试调用其他未同步的方法,则有可能。

线程A进入synchronized(StaticMyClass.class)或fooStatic方法的临界区后,任何线程都可以调用normalStatic吗?我认为,调用 fooStatic 和 normalStatic 可以独立调用,但是 barStatic 和 normalStatic 不能。如果错了,为什么?

其他未同步的方法可以独立调用,但是当您调用 barStatic() 时,不可能调用其他方法,因为您正在同步整个类。其他线程,必须等到当前线程完成执行。


查看完整回答
反对 回复 2021-08-25
  • 3 回答
  • 0 关注
  • 208 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信