views:

411

answers:

5

I'm wondering if this code will do any trouble:

I have a vector that is shared among many threads. Every time a thread has to add/remove stuff from the vector I do it under a synchronized block. However, the main thread has a call:

System.out.println("the vector's size: "+ vec.size());

which isn't synchronized.

Should this cause trouble?

+1  A: 

I assume you are referring to java.util.Vector.

Actually Vector.size() is synchronized and will return a value consistent with the vector's state at that time. If it returns 42, then at some point in time the vector contained 42 elements.

If you're adding items in a loop in another thread then you cannot predict the exact size, but it should be fine for monitoring purposes.

finnw
+3  A: 

All Vector methods are synchronized themselves, so as long as you are only synchronizing around a single method, your own synchronization is not necessary. If you have several method calls, which depend on each other, e.g. something like vec.get(vec.size()-2) to get the second last element, you have to use your own synchronization since otherwise, the vector may change between vec.size() and vec.get().

jarnbjo
A: 

Each of the methods of java.util.Vector is synchronized, so this won't cause any problems for something that is just logging the size.

To improve performance you may be better off replacing your Vector with an ArrayList. The methods of ArrayList aren't synchronized, so you would need to synchronize all access yourself.

Phil Ross
Which performance improvements do you expect if you replace the syncrhonized Vector class with an unsynchronized ArrayList and add your own synchronization around all method calls on the ArrayList?
jarnbjo
In many cases, single-method synchronization is insufficient, so you have to do your own synchronization anyway. Using Vector, you'd then end up synchronizing twice.
Michael Borgwardt
How much performance impact do you expect from the "double" synchronization if you implement something like `synchronized(vec) {vec.get(vec.size()-2);}`?
jarnbjo
If you manually synchronize on the vector itself, then the overhead is negligible. If you're synchronizing on another object, then there is more of an overhead (I've just done some quick tests that show ArrayList to be about 25% faster in this situation with no thread contention).
Phil Ross
A: 

Mind that you can always obtain a synchronized version of a collection by using Collections.synchronizedCollection(Collection<T> c) static method..

Jack
In this case the collection is a List, so Collections.synchronizedList(List<T> c) would be better.
finnw
A: 

There's no point whatsoever doing anything with a Vector in a synchronized block, because a Vector is already thread-safe. In fact, this practice could possibly lead to deadlocks/starvation, as your synchronized block may not be acquiring the same lock as that used internally by Vector.

In short, if you need a thread-safe implementation of List, there are much better options available in the JDK libraries. For example, if you need a thread-safe List which is frequently read and infrequently written (a common case) CopyOnWriteArrayList generally offers better performance than Vector.

Don