如果我有一个类,将其称为X,并且X包含一个集合(假设我没有使用其中一个同步集合,只是一个普通集合)。同步关键字 - 它是如何工作的?
如果我要写我自己的方法synchronized add() - 锁定工作如何?锁定是在X的实例上完成的,而不是在集合对象上完成的?
因此,同步我的add()方法不会阻止许多X实例调用add()并插入到集合中 - 因此我仍然可能遇到线程问题?
如果我有一个类,将其称为X,并且X包含一个集合(假设我没有使用其中一个同步集合,只是一个普通集合)。同步关键字 - 它是如何工作的?
如果我要写我自己的方法synchronized add() - 锁定工作如何?锁定是在X的实例上完成的,而不是在集合对象上完成的?
因此,同步我的add()方法不会阻止许多X实例调用add()并插入到集合中 - 因此我仍然可能遇到线程问题?
同步方法锁定对象。如果您的X.add
已同步,则会阻止同时执行同一对象的其他同步方法。如果任何超出该X
对象的人都可以访问相同的集合,则集合将不受保护。
如果您希望您的藏品受到保护,请确保它不能以除X
的同步方法以外的任何其他方式访问。另外,这在你的问题中有点不清楚,但是请注意,一个同步的非静态方法锁定了对象。假设每个X
实例都有自己的集合,它们不会互相干扰。
另一种选择,顺便说一句,是锁定集合,而不是X
对象:
void add(Object o) {
synchronized(myCollection) {
myCollection.add(o);
}
}
这将同步访问锁定的集合,而不是X
对象。使用你认为更容易和更有效的方法。
在您的示例中,将确保一次只有一个线程可以在该类的一个实例上调用该方法。其他方法可以访问该集合,这是不安全的。请查阅concurrent collections以获取有关线程安全收集实现的更多信息。
如果我要写我自己的方法synchronized add() - 锁定工作如何?锁定是在X的实例上完成的,而不是在集合对象上完成的?
锁定是在您同步的对象上完成的,而不是对象内的任何字段。为了锁定工作,所有的线程必须在同一个确切的对象上进行同步。通常最好锁定private final
对象。
private final Collection<...> myCollection = ...
...
synchronize (myCollection) {
myCollection.add(...);
}
虽然常见模式是锁住你要保护的对象,它真的可以是任何常量对象。你也可以这样做:
private final Object lockObject = new Object();
...
synchronize (lockObject) {
myCollection.add(...);
}
所以我同步add()方法不会从调用add(),并插入到收藏 - 因此,我仍然可以有线程问题停止X的多个实例?
如果你的应用程序的其他部分正在访问myCollection
没有是一个synchronized (myCollection)
块内,那么,你将有线程问题。您需要同步全部的访问权限才能正确保护收集并提供内存屏障。这意味着add(...)
,contains(...)
,迭代器等。
通常,如果您试图保护集合或其他类,那么将它包装在执行同步的类中是有意义的。这隐藏了锁定并保护了集合,使其不受代码中的缺失块的意外修改。
这是真的,你是跨共享许多x的实例一个集合?然后你需要在集合实例本身上进行同步。不要使方法本身,但将其所有代码包含在synchronized(coll) { ... }
块中。
另一方面,如果每个X都有自己的集合,那么synchronized add()
就是您所需要的。这将保证没有两个线程同时在同一个实例上执行add
。