"同步"背后发生了什么?

Aaj*_*jan 0 java multithreading synchronized

我知道为了使程序成为线程安全的,建议使用synchronized方法或代码块.疑问是下面的代码片段将如何使程序线程安全?幕后发生了什么?

public class MyCounter
{
    private int count = 0; // count starts at zero

    public synchronized void setCount(int amount)
    { 
        count = amount;
    }

    public synchronized int getCount()
    {
        return count;
    }
}
Run Code Online (Sandbox Code Playgroud)

Mad*_*apu 6

疑问是下面的代码片段将如何使程序线程安全?

这里的关键是每个java对象都有一个与之关联的隐式监视器,并且只有一个线程可以在任何时间点进入对象监视器,而其他尝试进入该监视器的线程将排队等待条目集或等待集.

当一个线程试图执行一个标记为synchronized它的方法时,应该获得该implicit monitor方法中执行代码之前的所有权.

在您的情况下,您有两种方法,都标记为synchronized.由于使用synchronized关键字,只有一个线程能够获取执行这些方法中任何一个所需的对象监视器,因此在任何时候只有一个线程可以执行这些synchronized方法,因此它们是线程安全的.

幕后发生了什么?

要了解对象监视器,所有权,等待集和条目集如何协同工作,让我们看一下代表implicit monitor每个java对象唯一的图片.正如我们所见,有两个入口点来获取监视器,即来自Entry Set或来自Wait Set.对于我们的讨论,我们将仅从Entry Set视角流动并假设为空Wait Set.

Java监视器条目集等待集

当线程调用synchronized方法时,它被放在Entry Set.

  • 如果没有线程当前拥有监视器且没有其他线程在条目集中等待,则该线程将成为监视器的所有者并开始执行代码.这称为活动线程.
  • 否则,如果有另一个拥有监视器的线程,则当前线程将被放置在其中,Entry set并且必须等待其中的其他现有线程Entry Set(如果有).

当前线程在等待Entry Set,

  • 当完成执行同步块中的代码时,活动线程将释放监视器.(其他发布方式是通过wait()我们讨论会忽略的方法)
  • 随后,由于监视器现在是空闲的,条目集中的线程将竞争获取监视器,其中一个将获得机会.

注意:如上所述,对于上面的讨论,我们假设Wait Set为了简单起见,没有线程可以保持讨论.Wait Set进入图片wait()notify()打电话.

我建议,有关监视器,条目集和等待集的详细说明,查看 https://www.artima.com/insidejvm/ed2/threadsynchP.html.