在java中声明一个对象为synchronized

发布于 2024-11-30 18:32:39 字数 179 浏览 1 评论 0原文

是否可以声明一个对象并同步以避免两个线程同时访问它?或者我需要在使用对象的每个点声明一个同步块?

我尝试过,但不可能以这种方式使用同步:

    public synchronized Vector<MyObject> myvector;

提前致谢

Is possible to declare an object and synchronized avoiding two threads access to it at the same time? or i'd need to declare a synchronized block in every point that object is used?

I tried but is not possible to use the synchronized that way:

    public synchronized Vector<MyObject> myvector;

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

自由如风 2024-12-07 18:32:39

矢量方法已经同步。在您的示例中,如果您只是向 myVector 添加/获取/删除对象,则不需要额外的同步。

从 Java 2 平台 v1.2 开始,该类已被改进为
实现List,使其成为Java集合的一部分
框架。与新的集合实现不同,Vector 是
已同步。

如果您创建一个具有内部成员字段的类,并且该类需要同步,那么是的,您需要同步对这些字段的访问。

Vector methods are synchronized already. In your example, you don't need additional synchronization if you're just adding/getting/removing objects to myVector.

As of the Java 2 platform v1.2, this class has been retrofitted to
implement List, so that it becomes a part of Java's collection
framework. Unlike the new collection implementations, Vector is
synchronized.

If you create a new class with internal member fields, and said class requires synchronization, then yes, you need to synchronize access to those fields.

十年九夏 2024-12-07 18:32:39

如果您使用其他集合,Collections 类中有一些方法可以同步集合。

List<MyObject> myList = Collections.synchronizedList( new ArrayList<MyObject> );

If you were using some other collection there are means within the Collections class to synchronized a collection.

List<MyObject> myList = Collections.synchronizedList( new ArrayList<MyObject> );
寂寞美少年 2024-12-07 18:32:39

据我所知,该关键字在该地方是非法的。但是,您可以使用线程安全的对象,例如向量,也可以使用synchronized(o){ ... } 代码块。

方法也可以同步,但过于频繁地使用它或在真正不需要同步的代码周围使用它会对性能产生负面影响。

As far as I know that keyword is illegal in that place. However you can use objects that are thread safe, such as Vectors or you can use synchronized(o){ ... } code blocks.

Methods may also be synchronized but using this too often or around code that really does not need the synchronization will have a negative effect on performance.

风追烟花雨 2024-12-07 18:32:39

这个问题有点两面性。您到底想要同步什么?访问变量的值还是访问变量值所持有的对象的方法?

如果是前者,则volatile关键字 最接近您所需要的。它与方法/块上的 synchronized 并不完全相同,但 volatile 变量的作用就好像它本身是同步的。

如果是后者,那就没必要了。 旧版 Vector 的方法类本身已经同步

This question is a bit two-fold. What exactly do you want to synchronize? The access to the variable's value or the access to the methods of the object which is hold by the variable's value?

If the former, then the volatile keyword comes closest what you need. It's not exactly like synchronized on methods/blocks, but the volatile variable acts as if it's synchronized on itself.

If the latter, then you don't need to. The methods of the legacy Vector class are by itself already synchronized.

回忆追雨的时光 2024-12-07 18:32:39

您需要通过委托模式进行同步:

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.

请注意,同步访问器方法不会执行此操作:

private volatile Vector<MyObject> myObjects;

public synchronized Vector<MyObject> getMyObjects() {
    return myObjects;
}

这只会在线程获取引用时进行同步,它们仍然可以在需要时使用该对象。

You need to synchronize via a delegatation pattern:

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.

Note that a synchronized accessor method won't do it:

private volatile Vector<MyObject> myObjects;

public synchronized Vector<MyObject> getMyObjects() {
    return myObjects;
}

That will just synchronize when threads get the reference, they can still use the object when they want.

幸福不弃 2024-12-07 18:32:39

Vector 一个同步集合,意味着它的状态是封装的,并且它的方法都是同步的。

但是,Vector 虽然是线程安全的,但不能保证复合操作的结果一致(检查项目是否存在然后执行某些操作),所以是的 - 您必须保护对向量的所有访问具有相同锁(内在或其他)的实例。这种策略有时称为“客户端锁定”。

但是,即使如此,在 Vector 的情况下(迭代器使用等),“完全同步”可能也很难实现。

如果可以的话,我建议您切换到一种更“现代”的并发集合实现(这意味着还要避免 Collections.synchronizedWHATEVER)。

供参考 - 包 java.util.concurrent

Vector is a synchronized collection, meaning that its state is encapsulated and its methods are all synchronized.

However, Vector, while being thread-safe, doesn't guarantee you consistent results on compound actions (check if items exists then do something), so yeah - you would have to guard all access to the vector instance with the same lock (intrinsic or otherwise). Such a policy is called sometimes "client-side locking".

But, even then, the "total synchronization" might be hard to achieve in case of Vector (iterator usage and such).

I would suggest, if you can, to switch to one of a more "modern" implementation of concurrent collections (that means also avoiding Collections.synchronizedWHATEVER).

For reference - Package java.util.concurrent

芸娘子的小脾气 2024-12-07 18:32:39

声明同步字段仅适用于 Java 中的基本类型。对象不能简单地通过声明其引用同步来同步——想象一下如果您尝试对同一个对象进行两个不同的引用会发生什么。

因此,您可以明白为什么不允许使用以下语法:

public ArrayList<Object> myList = new ArrayList<Object>();

public synchronized ArrayList<Object> mySyncedList = myList; 

//is the original list now synchronized or not?

不过您确实有一些解决方案:

1)如果您有权访问原始源代码,您可以手动同步它 - 也就是说,同步所有修改器,以便理论上不会出现任何问题。如果类很复杂,这可能会很棘手,但至少可以保证在任何使用该类的地方,它都是同步的。

public class MyCollection {
    public synchronized void addObject(Object a) {
        ...
    }
}

特别是,Vector 类是内部同步的,在您的示例中,无需对其进行更多同步。然而,您自己的类和许多 Java 类将没有这种保证。

2) 如果对象是 Java 库类,则可能有一种方法可以使用库功能来获取同步副本。这最常用于列表:

public List<Object> mySyncedList = Collections.synchronizedList(myList);

//pass around mySyncedList instead of myList to guarantee synchronization

3) 如果对象没有内部同步,并且没有提供获取其同步副本的方法,并且您没有能力编辑原始源代码,那么您别无选择但要同步修改对象的代码:

synchronized(myList) {
    myList.add(next);
}

但要注意:即使您自己的代码已同步,如果您向外部发布该对象的引用,那么使用您的类的任何程序员也必须同步对该对象的访问!

Declaring synchronized fields only works with the primitive types in Java. Objects cannot be synchronized simply by declaring their references synchronized--imagine what would happen if you tried to make two different references to the same Object.

Thus, you can see why the following syntax is not allowed:

public ArrayList<Object> myList = new ArrayList<Object>();

public synchronized ArrayList<Object> mySyncedList = myList; 

//is the original list now synchronized or not?

You do have a few solutions to this though:

1) If you have access to the original source code, you can manually synchronize it--that is, synchronize all the mutators so that no issues could theoretically arise. This can be tricky if the class is complex, but at least you are guaranteed that anywhere that class is used, it is synchronized.

public class MyCollection {
    public synchronized void addObject(Object a) {
        ...
    }
}

In particular, the Vector class is internally synchronized and in your example there is no need to put more synchronization on it. However, your own classes and many Java classes will not have this guarantee.

2) If the Object is a Java library class, there may be a way to obtain a synchronized copy using library functionality. This is most often used for lists:

public List<Object> mySyncedList = Collections.synchronizedList(myList);

//pass around mySyncedList instead of myList to guarantee synchronization

3) If the Object is not internally synchronized, and does not provide a way to obtain a synchronized copy of it, and you do not have the ability to edit the original source code, you have no choice but to synchronize the code that modifies the object:

synchronized(myList) {
    myList.add(next);
}

Beware though: even if your own code is synchronized, if you publish a reference of that Object to the outside, then any programmer that uses your classes will also have to synchronize access to that Object!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文