Java 同步块(synchronized block)

标签 java multithreading synchronization

如果我们有一个方法:

public void doSomething(){
    synchronized(this){
        //some code processing here
    }
    String temp = "init"; //instead of i++
    synchronized(this){
        //some other code processing here
    }
}

这个方法等同于public synchronized void doSomething()吗?

是否有任何理由假设某些执行中的线程调度器不会产生与同步整个函数相同的有效流程?即:

  • Thread1 进入第一个同步块(synchronized block)。
  • Thread2 block 。
  • Thread1 继续 i++ 并移动到第二个同步块(synchronized block),而 Thread2 仍处于阻塞状态。
  • 因此,Thread2Thread1 退出两个同步块(synchronized block)后进入方法。

我只需要知道:

  • 我能否指望两个线程(Thread1Thread2)可以同时在方法中的所有执行上下文?例如第一个同步块(synchronized block)中的Thread2和第二个同步块(synchronized block)中的Thread1实现并发。
  • 会不会有一些执行流程在方法中只有一个线程(一次)有效地序列化整个流程,使其等同于 public synchronized void doSomething()

最佳答案

一些 执行中,它会与同步整个函数有相同的流程,当然 - 但要真正等同于使方法同步,它必须有相同的流程 < em>所有处决。

实际上,另一个线程有可能在执行到一半时获取锁(无论是针对此方法还是锁定在同一监视器上的某些其他代码)。如果方法本身是同步的,则不会发生这种情况,因此它们不等价。

(顺便说一句,无论如何,锁定 this 通常被认为是不好的做法;我不记得我上次编写同步方法是什么时候了。我改为锁定私有(private)监视器,所以我知道我的代码是唯一可以锁定它们的代码。)

编辑:回应您的编辑:

All I need to know is whether I can count on all execution contexts that both threads (e.g. Thread1 and Thread2) can be in the method at the same time, e.g thread2 in the first sync block and thread1 in the second sync block to achieve concurrency

绝对不是!保证您不会在同一个监视器上同步的同步块(synchronized block)中有两个线程。

您有三部分代码:第一个同步块(synchronized block)、非同步部分和第二个同步部分。

任何数量的线程都可以同时在非同步部分执行。对于任何一个实例(因为您在 this 上进行同步)只有一个线程可以执行同步块(synchronized block)中的任一个。如果要实现并发,则必须在不同的监视器上进行同步。

此外,听起来您希望调度程序保证让另一个线程在等待锁时获取锁。我不相信有任何这样的保证——执行第一个 block 的线程可以释放锁,但在同一时间片中继续并在任何其他线程进入之前重新获取它。在某些 JVM 中,这可能不会发生,但我不会不要相信它有任何保证。

关于Java 同步块(synchronized block),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3403030/

相关文章:

.net - 未完成的结束线程^

spring - 是否可以使用 Spring Boot 运行较长的任务?

java - 每秒执行一次方法

MongoDB 同步开发和生产数据库

java - 线程不同步

java - 在 InputStream 之前获取 FileSize

java - double 到 long 无需在 Java 中进行转换

Java 1.4 到 Java 1.5 - 重写代码并避免 @SuppressWarnings

synchronization - 使用现有主服务器创建新的从服务器 - 初始数据库创建过程是什么样的?

java - 多线程应用程序连续失败后如何将主机名添加到阻止列表?