有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程Java同步块

如果我们有一个方法:

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进入第一个同步块
  • Thread2
  • Thread1继续执行i++并移动到第二个同步块,而Thread2仍处于阻塞状态
  • 因此,Thread2Thread1退出两个同步块后进入该方法

我只需要知道:

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

共 (4) 个答案

  1. # 1 楼答案

    不,它不等同于synchronized void doSomething(),因为i++不是原子操作。事实上,它可能有类似的作用

    int temp = i; i = i + 1; result = temp

    如果这些操作不是原子化的,那么i的值可以在其处于不良状态时读取

  2. # 2 楼答案

    此方法与使其成为同步方法不同。 你解释的行为可能会被看到,但永远无法得到保证

  3. # 3 楼答案

    不,不是。例如上面的代码

    线程一进入第一个同步块,执行它,然后退出,然后被关闭。 线程2进入第一个同步块执行它,然后在被关闭之前进入第二个同步块。 线程一现在无法继续,直到线程二退出第二个同步块

    如果整个方法是同步的,这种模式就不会发生

  4. # 4 楼答案

    一些执行中,它将具有与同步整个函数相同的流程,这是肯定的——但为了真正等同于使方法同步,它必须具有与所有执行相同的流程

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

    (顺便说一句,锁定this通常被认为是不好的做法;我不记得上次我写了一个同步的方法。我锁定了私人持有的监视器,因此我知道我的代码是唯一可能锁定它们的代码。)

    编辑:要响应您的编辑:

    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

    绝对不是!可以保证不会在同一个监视器上同步同步一个同步块中的两个线程

    代码有三个部分:第一个同步块、未同步部分和第二个同步部分

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

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