Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 - Fatal编程技术网

Java 同步语句-同步方法和同步语句等效吗?

Java 同步语句-同步方法和同步语句等效吗?,java,multithreading,Java,Multithreading,对于此简单的同步语句: public void addName(String name) { synchronized(this) { // line1 lastName = name; nameCount++; } nameList.add(name); } public void addName(String name) { synchronized(this) { //line1 lastName = na

对于此简单的同步语句:

public void addName(String name) {
    synchronized(this) { // line1
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}
public void addName(String name) {
    synchronized(this) {  //line1
        lastName = name;
        nameCount++;

        nameList.add(name);
    }
}
似乎两个线程(比如说
t1
t2
可以同时调用
addName
方法,但是一旦得到注释为
line1
的行,只有一个线程可以继续,这意味着其他线程必须挂起。这意味着即使将
nameList
放在synchronized语句之外,也可以保证
nameList
不会被多个线程冲突

这是真的吗?如果是,那么如果在synchronized语句之前不需要执行任何操作,那么以下方法之间是否有任何区别:

public void addName(String name) {
    synchronized(this) { // line1
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}
public void addName(String name) {
    synchronized(this) {  //line1
        lastName = name;
        nameCount++;

        nameList.add(name);
    }
}
或:


我很清楚

void synchronized add(){

}
同:

void add(){
  synchronized(this){

  }
}
让我困惑的是,在
addName
示例中,我认为执行顺序可能如下所示:

t1:synchronized steatement
t1:nameList.add
t2:synchronized steatement
t2:nameList.add
这意味着
synchronized语句
nameList.add之间没有其他线程的执行更改。因此,将
名称列表添加到同步块外部的内部没有区别

但事实上,@JB Nizet的答案可能是这样的:

t1:synchronized steatement
t2:synchronized steatement

t2:nameList.add
t1:nameList.add

然后,将
名称列表放在块的外部或内部是很重要的。

最后两个片段是等效的,但第一个片段不是

在第一个代码段中,假设添加到列表中的内容不是同步块的一部分,两个线程可以同时执行此指令。如果列表不是线程安全的,那么它就是一个问题


即使列表是线程安全的,这也可能是一个问题,因为对状态的各个部分(计数、姓氏和列表)的更改不是原子化的。因此,其他线程可能会看到姓氏的新值,但在列表中找不到该姓氏

它们是等价的(最后两个)。哦,是的,我忘记了:)有很多关于同步方法和块之间差异的链接或相关问题。谢谢你,我知道了,我想一个线程会调用
名称列表。一旦同步语句完成,就添加
,没有任何其他线程可以交错。但实际上,
nameList.add
可以同时访问。