我们有一项任务要完成,dummyMethod.

private synchronized void dummyMethod(){
    Log.d("debug", "do nothing in dummyMethod()")
}

我们将该任务运行了几次.

private synchronized void fooMethod() throws InterruptedException{
    
    for (int i = 0; i < 10; i++){
        dummyMethod();
    }
   
   Thread.sleep(10000)
   Log.d("debug", "fooMethod() finished")
}

在上述代码同步的情况下,立即执行dummyMethod() 10次.

然而,在下面的代码中,dummyMethod()只被立即调用一次,并且只有在fooMethod()完成之后,它才被完成并执行9次.

private synchronized void fooMethod() throws InterruptedException{
    
 new Thread(()->{
    for (int i = 0; i < 10; i++){
        dummyMethod();
    }
 }).start();
   
   Thread.sleep(10000)
   Log.d("debug", "fooMethod() finished")
}

在本例中,logcat显示:

Long monitor contention with owner main (18077) at void ...fooMethod()(MainActivity.java:1106) waiters=0 in void ...MainActivity.dummyMethod() for 10.001s

我认为在后一种情况下,它不会被新的线程阻塞.有谁能解释一下这件事吗?一个同步的方法如何在一个新线程中多次异步运行另一个同步的方法?

推荐答案

从我的 comments 来看-

从这个Baeldung article: all synchronized blocks of the same object can have only one thread executing them at the same time

因此,当前线程已经处于同步方法中,新线程不能立即执行dummyMethod(),因为它是同一个对象.

稍微修改一下原始代码,显示新实例的使用确实允许新的Thread立即运行dummyMethod():

package sandbox;

public class SyncTest {

    public static void main(String[] args) throws InterruptedException {
        var test = new SyncTest();
        test.fooMethod();
    }

    private synchronized void dummyMethod() {
        System.out.println("do nothing in dummyMethod()");
    }

    private synchronized void fooMethod() throws InterruptedException {
        var t = new SyncTest(); // new instance will have its own monitor
        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                t.dummyMethod();
            }
        }).start();

        Thread.sleep(10000);
        System.out.println("fooMethod() finished");
    }
}

Java相关问答推荐

如何审查Java dtos中的自定义注释字段?

如何转换Tue Feb 27 2024 16:35:30 GMT +0800 String至ZonedDateTime类型""

如何在Java中声明未使用的变量?

在for—each循环中的AnimationTimer中的if语句'

ApachePOI:不带换行的新行

SpringBoot+Java 17@Valid未验证POJO

计算两个浮点数之间的距离是否对称?

Spring和可编辑";where";@Query

生成桥方法以解决具有相同擦除的冲突方法

Java17支持哪个MapR版本?

虚拟线程应该很快消亡吗?

在Java中将int[]矩阵添加到ArrayList中,但出现错误

Spring Boot&;Docker:无法执行目标org.springframework.boot:spring-boot-maven-plugin:3.2.0:build-image

如何从HttpResponse实例获取Entity对象的内容?

如何处理两个几乎相同的XSD文件?

不能在 map 上移除折线

如何在Struts2中使用操作类中的结果注释重定向到不同的命名空间

使用@ExceptionHandler的GlobalExceptionHandler还是来自服务器的REST应答的ResponseEntity?

SonarQube在合并升级到java17后对旧代码提出错误

双对象供应商