在java中声明一个对象为synchronized
是否可以声明一个对象并同步以避免两个线程同时访问它?或者我需要在使用对象的每个点声明一个同步块?
我尝试过,但不可能以这种方式使用同步:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
矢量方法已经同步。在您的示例中,如果您只是向
myVector
添加/获取/删除对象,则不需要额外的同步。如果您创建一个具有内部成员字段的新类,并且该类需要同步,那么是的,您需要同步对这些字段的访问。
Vector methods are synchronized already. In your example, you don't need additional synchronization if you're just adding/getting/removing objects to
myVector
.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.
如果您使用其他集合,Collections 类中有一些方法可以同步集合。
If you were using some other collection there are means within the Collections class to synchronized a collection.
据我所知,该关键字在该地方是非法的。但是,您可以使用线程安全的对象,例如向量,也可以使用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.
这个问题有点两面性。您到底想要同步什么?访问变量的值还是访问变量值所持有的对象的方法?
如果是前者,则
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 likesynchronized
on methods/blocks, but thevolatile
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 alreadysynchronized
.您需要通过委托模式进行同步:
请注意,同步访问器方法不会执行此操作:
这只会在线程获取引用时进行同步,它们仍然可以在需要时使用该对象。
You need to synchronize via a delegatation pattern:
Note that a synchronized accessor method won't do it:
That will just synchronize when threads get the reference, they can still use the object when they want.
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
声明同步字段仅适用于 Java 中的基本类型。对象不能简单地通过声明其引用同步来同步——想象一下如果您尝试对同一个对象进行两个不同的引用会发生什么。
因此,您可以明白为什么不允许使用以下语法:
不过您确实有一些解决方案:
1)如果您有权访问原始源代码,您可以手动同步它 - 也就是说,同步所有修改器,以便理论上不会出现任何问题。如果类很复杂,这可能会很棘手,但至少可以保证在任何使用该类的地方,它都是同步的。
特别是,
Vector
类是内部同步的,在您的示例中,无需对其进行更多同步。然而,您自己的类和许多 Java 类将没有这种保证。2) 如果对象是 Java 库类,则可能有一种方法可以使用库功能来获取同步副本。这最常用于列表:
3) 如果对象没有内部同步,并且没有提供获取其同步副本的方法,并且您没有能力编辑原始源代码,那么您别无选择但要同步修改对象的代码:
但要注意:即使您自己的代码已同步,如果您向外部发布该对象的引用,那么使用您的类的任何程序员也必须同步对该对象的访问!
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:
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.
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:
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:
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!