5

现在,我不确定这是否是一个愚蠢的问题,如果是,请多多包涵。

对象上的锁是“递归的”吗,即如果两个对象在其字段中引用了第三个对象,并且一个线程正在两者之一上运行同步方法,那么任何其他线程都可以访问第三个对象吗?

// a and b are some objects that implement Runnable
// they both reference the same third object
a.ref = c;
b.ref = c;

// a is run in a thread and processes some data in a loop for a long time
// the method the loop belongs to is declared synchronized
threadA = new Thread(a);
threadA.start();

a.someSyncedMethod(); // this would block ...
b.ref.someOtherSyncedMethod(); // ... but would this?
a.ref.someOtherSyncedMethod(); // ... and how about this?
4

3 回答 3

10

值得将“锁”和“锁定对象”的概念分开。没有真正的“锁定对象”的概念——“获取(和释放)”与对象关联的锁。是的,这听起来像是我在吹毛求疵——但区别很重要,因为如果你谈论一个对象被锁定,听起来好像没有其他线程能够在持有该锁定时更改对象中的任何内容。

相反,它只是意味着在持有锁时没有其他线程能够获取相同的锁。锁与与锁关联的对象的任何内容之间没有直接关系。

声明为“同步”的方法获取与它们所属对象的实例关联的锁。这只会使同一对象上的其他同步方法等待,并在其上显式同步的同步语句。

就我个人而言,我不喜欢同步方法 - 我喜欢通过显式同步仅用于同步的(私有,最终)成员变量来使其更清晰。

于 2009-03-04T10:19:30.543 回答
1
a.someSyncedMethod(); // this would block ...

仅当您将运行方法标记为同步或使 ThreadA 在同步方法中运行代码时。

在 JVM 中,每个对象都拥有所谓的监视器。一次只有一个线程可以拥有与给定对象关联的监视器。同步是您告诉当前线程在继续之前获取监视器的方法。

类本身也拥有一个静态方法的监视器。

于 2009-03-04T10:20:10.667 回答
0

“锁”的含义(实际上这个变体被称为监视器)完全是一种约定,没有强制访问限制。

该功能依赖于所有对象都表现良好并在访问数据之前获取相应的锁。只有通过使用适当的访问控制将这种期望的行为封装在一个类中,您才能为客户端对象强制执行它。

于 2009-03-04T10:26:08.797 回答