现在,我不确定这是否是一个愚蠢的问题,如果是的话,请耐心等待。
对象上的锁是“递归的”,i。即如果两个对象在其字段中引用了第三个对象,并且一个线程正在其中一个上运行同步方法,那么任何其他线程是否可以访问第三个对象?
// 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?
答案 0 :(得分:10)
值得分离出“锁定”和“锁定对象”的概念。没有关于“锁定对象”的真正想法 - “获取(和释放)”与对象相关联的锁。是的,这听起来像是在挑剔 - 但区别很重要,因为如果你谈论一个对象被锁定,听起来没有其他线程可以改变对象中的任何东西,而那个锁是保持。
相反,它只是意味着在锁定时没有其他线程能够获取相同的锁。锁与锁定所关联的对象的任何内容之间没有直接关系。
声明为“synchronized”的方法获取与其所属对象的实例关联的锁。这只会使同一对象上的其他同步方法等待,并在其上显式同步的同步语句。
我个人不喜欢同步方法 - 我希望通过显式同步一个仅用于同步的(私有的,最终的)成员变量来使它更清晰。
答案 1 :(得分:1)
a.someSyncedMethod(); // this would block ...
仅当您使用synchronized标记run方法或在同步方法中使用ThreadA运行代码时。
在JVM中,每个对象都拥有所谓的监视器。一次只有一个线程可以拥有与给定对象关联的监视器。 Synchronized是在继续之前告诉当前线程获取监视器的方法。
此类本身也拥有静态方法的监视器。
答案 2 :(得分:0)
“锁定”的含义(实际上这种变体称为监视器)完全是一种约定,不会强制执行访问限制。
在访问数据之前,功能依赖于所有正常运行的对象并获取相应的锁。只有通过在具有适当访问控制的类中封装此所需行为,您才能为客户端对象强制执行该行为。