Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java “背后发生了什么?”;同步的;?_Java_Multithreading_Synchronized - Fatal编程技术网

Java “背后发生了什么?”;同步的;?

Java “背后发生了什么?”;同步的;?,java,multithreading,synchronized,Java,Multithreading,Synchronized,我知道为了使程序线程安全,建议使用synchronized方法或代码块。问题是下面的代码片段如何使程序线程安全?幕后发生了什么 public class MyCounter { private int count = 0; // count starts at zero public synchronized void setCount(int amount) { count = amount; } public synchroniz

我知道为了使程序线程安全,建议使用
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;
    }
}
如果我们有Thread1、Thread2和Thread3,其中前两个等待释放,第三个等待释放,顺序如下

Thread1进入并调用
wait()

Thread2进入并调用
wait()

Thread3进入并调用
notifyAll()

始终使用螺纹3饰面

但是,等待的线程没有特定的顺序。
哪个先执行,完全是随机的,与调用
wait()
的顺序无关。但是,调用notify(All)的线程总是在任何等待线程继续之前完成。

公共同步的void setCount(int amount)
public synchronized void setCount(int amount)
{ 
        count = amount;  <-- *this operation is not atomic, and hence multiple thread execution may interleave resulting in race conditions*
}
{ 计数=金额; 问题是下面的代码片段将如何生成该程序 线程安全

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

当线程尝试执行标记为
synchronized
的方法时,它应该在执行该方法中的代码之前获得
隐式监视器的所有权

在您的例子中,有两个方法,都标记为
synchronized
。由于使用
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;
    }
}
为了理解对象监视器、所有权、等待集和条目集是如何协同工作的,让我们拍摄下面的图片,它代表了一个
隐式监视器
,对于每个java对象都是唯一的。正如我们看到的,有两个入口点可以获取监视器,即从
条目集
或从
等待集
因此,我们将仅从
条目集
透视图中查看流,并假设一个空的
等待集

当线程调用
synchronized
方法时,它被放置在
条目集中

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

  • 在同步块中执行完代码后,活动线程将释放监视器。(另一种释放方式是通过
    wait()
    方法,我们将在讨论中忽略该方法)
  • 随后,由于监视器现在空闲,条目集中的线程将竞争获取监视器,其中一个线程将获得机会
注意:如上所述,对于上述讨论,为了简单起见,我们假设
等待集
中没有线程。等待集
包含
等待()
通知()
调用


我建议,值得一看关于监视器、入口集和等待集的更详细的解释。

使代码线程安全不是简单的“同步”问题。即使是基本的理解也需要一个教程,这对本网站来说太长了。坦率地说,它提供了很多清晰性。;)