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
可以同时访问。