在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);
}