基本上如果你有以下内容会发生什么:
class SyncTest {
private final static List<Object> mObjectList = new ArrayList<Object>();
public synchronized void mySyncMethod(Object object) {
new Thread(new Runnable() {
public void run() {
synchronized (SyncTest.this) {
for (int i = 0; i < mObjectList.size(); i++) {
//Do something with object
}
}
}
}).start();
}
}
答案 0 :(得分:3)
外部synchronized
确保单线程访问创建新Thread
的过程,而内部synchronized
确保单线程访问for
循环。
当然你意识到编写代码并没有多大意义,因为内部this
引用是针对你的匿名内部类。我认为你的意思是SyncTest.this
,所以你正在同步SyncTest
类的访问权限。更好的方法是同步访问mObjectList
。
在内部课程this
修复后写入时,Thread
会阻止mySyncMethod
返回。
根据您的工作情况,您可能最好使用其中一种Concurrent
集合类型,而不是同步对List
的访问权限,因为您可以获得更好的并发性。
答案 1 :(得分:3)
Re-entrancy不适用于此处。这里嵌套的唯一影响是允许内部类实例访问封闭实例(包括正在使用的锁)。同步的两件事在不同的线程中调用。创建新线程之前必须由调度程序选择才能运行,因此即使这些线程使用相同的锁定,两者之间也不会有太多重叠。
调用mySyncMethod的线程获取它正在使用的SyncTest实例上的锁,然后它创建一个新的Thread,启动它,然后释放锁并继续前进。
稍后,一旦新线程启动,它必须获取启动它的SyncTest对象上的锁,然后才能执行其run方法。如果SyncTest上的锁被其他东西使用(刚刚创建它的线程,在同一个SyncTest实例上另一个调用mySyncMethod,或者在同一个SyncTest实例上另一个调用mySyncMethod创建的另一个线程),则必须等待锁定。然后它会对列表执行任何操作,到达方法的末尾并释放锁。
这里有很多问题:
目前还不清楚为什么你需要创建自己的线程而不是使用池,或者为什么创建方法需要同步并等待新线程在它释放锁之前启动。
SyncTest对象上的锁没有被封装,所以其他东西可能正在获取它,目前还不清楚是什么东西争夺锁。
由于列表被定义为静态类成员,因此您有多个SyncTest对象;你会有单独的线程搞乱相同的列表,但使用不同的锁,所以很难理解锁定点是什么。
但你所展示的并不会陷入僵局。
答案 2 :(得分:0)
什么都不会发生,synchronization
与线程有关,所以即使你重新进入同步块很多次,如果同步的所有者是相同的线程。
答案 3 :(得分:0)
mySyncMethod()仅在调用它的线程可以获得SyncTest实例中的锁的所有权时运行。
run方法可以在其不同的线程中启动,但会在同步语句上阻塞,直到THAT线程获得同一SyncTest实例的锁的所有权。
(答案假设&#39;这个&#39;指的是外部类实例,在编辑中更正了原始帖子)
答案 4 :(得分:0)
如果方法中有同步块,则锁定仅在该块上。并且方法内部的块可以具有不同的对象锁定。