据我了解以下代码,在synchronized
块中,this
是计数器的实例。
问题1:在下面的示例中,这是否意味着当线程A到达synchronized
块时,线程B被禁止对Counter实例执行任何操作?换句话说,这是否意味着线程可以按照他们的意愿继续执行,但是一旦到达synchronized
块,另一个就停止对类执行任何操作,直到该块退出为止?
public class Counter {
public void increment() {
// Some code
synchronized (this) { // <---- "this" is an instance of Counter
// Some more code
}
}
}
将上面的代码与
public class Counter {
List<String> listOfStrings = new ArrayList<String>();
public void increment() {
// Some code
synchronized (listOfStrings) {
// Some code that deals with
// listOfStrings
}
}
}
问题2:在上面的示例中,一旦线程A到达
synchronized
块,线程B即可继续读取和写入该类中的任何内容,但listOfStrings
ArrayList是mutex
块中的synchronized
。这样对吗?问题3:是否进一步假设我们需要对多个对象进行修改,而
this
是我们应该使用的mutex
吗?例如:
public class Counter {
List<String> listOfStrings = new ArrayList<String>();
List<Integers> listOfIntegers = new ArrayList<Integers>();
public void increment() {
// Some code
synchronized (this) {
// Some code that deals with
// listOfStrings and listOfIntegers
}
}
}
我理解正确吗?如果我遗漏了任何东西,请更正。
最佳答案
线程B被阻止对Counter实例执行任何操作?
不,线程B被阻止输入同步的代码块,它仍然可以输入其他方法:那些未同步的方法和那些使用不同对象同步的方法。线程B不能仅访问使用已由其他线程占用的对象进行同步的块(同步锁是可重入的)。
线程B可以继续读写类中的任何内容,但listOfStrings
除外
并非如此,将listOfStrings
用作一个synchronized
块中的互斥体这一事实并不意味着其他线程无法显式访问该对象。这仅意味着其他线程无法访问由同一对象保护的同步块。因此,如果要保护对listOfStrings
对象的访问,则必须同步访问该对象的所有方法,并使用相同的锁(例如listOfStrings
)。
顺便说一句,您同步的每个对象都应该使用final
以避免麻烦。
假设是否需要对多个对象进行修改,这是否是正确的假设呢?
是的,没有。考虑以下情况:
List<String> listOfStrings = new ArrayList<String>();
List<Integers> listOfIntegers = new ArrayList<Integers>();
Set<String> setOfStrings = new HashSet<String>();
Set<Integers> setOfIntegers = new HashSet<Integers>();
如果一个方法仅访问列表,而第二个方法仅访问集合,则可以安全地使用两个锁-第一个方法用于一个锁,第二个方法用于第二个锁。在
this
上进行同步不会受到影响,但会影响性能:private final Object listLock = new Object();
private final Object setLock = new Object();
然后:
synchronized (listLock) {
// Some code that deals with
// setOfStrings and setOfIntegers
}
//...
synchronized (setLock) {
// Some code that deals with
// setOfStrings and setOfIntegers
}