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
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.
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> );
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.
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
.
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.
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
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!
精彩评论