当我们说我们使用synchronized关键字锁定一个对象时,这是否意味着我们正在获取整个对象上的锁,还是只在块中存在的代码上获得锁?
在下面的示例中,listOne.add是同步的,这是否意味着如果另一个线程访问listOne.get,它将被阻塞,直到第一个线程离开这个块?当第一线程仍在synchronized块中时,如果第二个线程访问同一对象的实例变量上的listTwo.get或listTwo.add方法,该怎么办?
List<String> listONe = new ArrayList<String>();
List<String> listTwo = new ArrayList<String>();
/* ... ... ... */
synchronized(this) {
listOne.add(something);
}发布于 2011-03-27 18:53:49
给定以下方法:
public void a(String s) {
synchronized(this) {
listOne.add(s);
}
}
public void b(String s) {
synchronized(this) {
listTwo.add(s);
}
}
public void c(String s) {
listOne.add(s);
}
public void d(String s) {
synchronized(listOne) {
listOne.add(s);
}
}您不能同时调用a和b,因为它们被锁定在同一个锁上。但是,您可以同时调用a和c(显然是使用多个线程),因为它们不是锁定在同一个锁上。这可能会给listOne带来麻烦。
你也可以同时调用a和d,因为在这个上下文中d和c没有什么不同,它不使用相同的锁。
重要的是,您始终使用相同的锁来锁定listOne,并且不允许在没有锁的情况下访问它。如果listOne和listTwo在某种程度上是相关的,并且有时需要同时/原子地更新,那么你需要一个锁才能访问它们。否则,两个单独的锁可能更好。
当然,如果您需要的只是一个并发列表,那么您可能会使用相对较新的java.util.concurrent类:)
发布于 2011-03-27 18:40:55
锁位于包含在synchronized块中的对象实例上。
但是要小心!这个对象是的,而不是本质上锁定的,不能被其他线程访问。只有执行相同synchronized(obj)的线程才会等待该锁,在您的示例中obj是this,但在其他线程中也可以是一个变量引用。
因此,不执行任何同步语句的线程可以访问“锁定”对象的任何和所有变量,您可能会遇到竞争条件。
发布于 2011-03-27 18:37:53
如果您在同一实例上有一个synchronized块,则其他线程仅会阻塞。因此,列表本身上的任何操作都不会阻塞。
https://stackoverflow.com/questions/5448681
复制相似问题