在java中将对象声明为已同步
是否可以声明一个对象并同步以避免两个线程同时访问它?或者我需要在对象使用的每个点上声明一个同步块 我尝试过,但无法以这种方式使用同步:在java中将对象声明为已同步,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,是否可以声明一个对象并同步以避免两个线程同时访问它?或者我需要在对象使用的每个点上声明一个同步块 我尝试过,但无法以这种方式使用同步: public synchronized Vector<MyObject> myvector; 公共同步向量myvector; 提前感谢矢量方法已经同步。在您的示例中,如果只是向myVector添加/获取/删除对象,则不需要额外的同步 从Java2平台v1.2开始,该类已被改装为 实现列表,使其成为Java集合的一部分 框架与新的集合实现不
public synchronized Vector<MyObject> myvector;
公共同步向量myvector;
提前感谢矢量方法已经同步。在您的示例中,如果只是向
myVector
添加/获取/删除对象,则不需要额外的同步
从Java2平台v1.2开始,该类已被改装为
实现列表,使其成为Java集合的一部分
框架与新的集合实现不同,Vector是
同步的
public class MyCollection {
public synchronized void addObject(Object a) {
...
}
}
如果您创建了一个包含内部成员字段的新类,并且该类需要同步,那么是的,您需要同步对这些字段的访问。据我所知,关键字在该位置是非法的。但是,您可以使用线程安全的对象,例如向量,也可以使用同步(o){…}代码块
方法也可能是同步的,但如果过于频繁地使用此方法,或者在确实不需要同步的代码周围使用此方法,则会对性能产生负面影响。如果您使用的是其他集合,则Collections类中存在同步集合的方法
List<MyObject> myList = Collections.synchronizedList( new ArrayList<MyObject> );
List myList=Collections.synchronizedList(新的ArrayList);
这个问题有点双重性。您到底想要同步什么?对变量值的访问,还是对由变量值持有的对象的方法的访问
如果是前者,那么最接近你所需要的。它与方法/块上的synchronized
不完全相同,但是volatile
变量的作用就好像它自己是同步的一样
如果是后者,那么你不需要。的方法本身已同步您需要通过删除模式进行同步:
private volatile Vector<MyObject> myObjects;
public synchronized boolean addMyObject(MyObject o) {
return myObjects.add(o);
}
// etc for other methods of Vector that you want to expose.
私有易失性向量myObjects;
公共同步布尔addMyObject(MyObject o){
返回myObjects.add(o);
}
//等,以获取要公开的向量的其他方法。
请注意,同步访问器方法无法完成此操作:
private volatile Vector<MyObject> myObjects;
public synchronized Vector<MyObject> getMyObjects() {
return myObjects;
}
私有易失性向量myObjects;
公共同步向量getMyObjects(){
返回对象;
}
当线程获得引用时,这将只是同步,它们仍然可以在需要时使用对象。
Vector
是一个同步的集合,这意味着它的状态被封装,它的方法都是同步的
然而,Vector
,虽然是线程安全的,但不能保证复合操作的结果一致(检查项目是否存在,然后做些什么),因此是的-您必须使用相同的锁(内在或其他)来保护对Vector实例的所有访问。这种策略有时称为“客户端锁定”
但是,即使这样,“完全同步”在向量的情况下也很难实现(迭代器的使用等等)
如果可以的话,我建议您切换到一种更“现代”的并发集合实现(这意味着也要避免collections.synchronizedWHATEVER
)
仅供参考-声明同步字段仅适用于Java中的基元类型。仅通过声明对象的引用已同步,无法同步对象——想象一下,如果尝试对同一对象进行两个不同的引用,会发生什么情况
因此,您可以看到为什么不允许使用以下语法:
public ArrayList<Object> myList = new ArrayList<Object>();
public synchronized ArrayList<Object> mySyncedList = myList;
//is the original list now synchronized or not?
特别是,Vector
类是内部同步的,在您的示例中,不需要对其进行更多的同步。但是,您自己的类和许多Java类都没有这种保证
2) 如果对象是Java库类,则可能有一种使用库功能获取同步副本的方法。这通常用于列表:
public List<Object> mySyncedList = Collections.synchronizedList(myList);
//pass around mySyncedList instead of myList to guarantee synchronization
但是要小心:即使您自己的代码是同步的,如果您将该对象的引用发布到外部,那么任何使用您的类的程序员也必须同步对该对象的访问
synchronized(myList) {
myList.add(next);
}