Suppose i have a code snippet where i want to insert a node in a Linked List and for consistency i used following coding mechanism : Assume that current and next are elements of LinkedList where current represent the Object we are working on and next represent the next object of List.
synchronized(current) {
synchronized(next) {
.............
}
}
and i performed an insertafter for current Object. Can the same functionality be achieved through synchronized methods. Since we can obtain lock only on a single object. So synchronized insertAfter wont prevent someone to use insertBefore.
A synchronized method is nothing but syntactic sugar for synchronized(this) {...}.
So the literal answer to your question is "not easily". You would need two different objects where the two synchronized methods are declared, and call one from the other. But it seems like a bad idea.
In general, I question the goal of trying to reduce an explicit synchronized block to a synchronized method. Synchronized blocks are more readable, and let you encapsulate the lock object to prevent undesired lock contention if some other code decides to use the same instance as the lock for some reason.
Also, are you sure you need the kind of fine-grained locking you're trying to do? This seems error-prone... a more straightforward code would synchronize on the same object for any operation on the list.
This pattern is well know to result in what is called deadly embrace. Imagine someone else making use of your code and also doing the equivalent of an insertBefore:
synchronized(next) {
synchronized(current) {
.............
}
}
This would obviously end in tears.
The obvious answer is not to synchronize on the nodes but on the joins between the nodes.
Related
I have a data structure that I occasionally wish to modify, and occasionally wish to replace outright. At the moment, I'm storing this in an AtomicReference, and using synchrnonized blocks (synchronized on the AtomicReference itself, not its stored value) when I need to modify it, rather than replace it.
So something like:
public void foo(AtomicReference reference){
synchronized(reference){
reference.get()
.performSomeModification();
}
}
Notice that the modifying call is a member of the wrapped value, not the atomic reference, and is not guaranteed to have any thread safety of its own.
Is this safe? Findbugs (a freeware code reviewing tool) had this to say about it, so now I'm worried there's something happening under the hood, where it may be prematurely releasing the lock or something. I've also seen documentation referencing AtomicReference as specifically for immutable things.
Is this safe? If it isn't I could create my own Reference-storing class that I would be more certain about the behavior of, but I don't want to jump to conclusions.
From the linked documentation:
For example, synchronizing on an AtomicBoolean will not prevent other threads from modifying the AtomicBoolean.
It can't prevent other threads from modifying the AtomicBoolean because it can't force other threads to synchronize on the AtomicBoolean.
If I understand your question correctly, your intention is to synchronize calls to performSomeModification(). The code you've written will achieve that, if and only if every call to performSomeModification() is synchronized on the same object. As in the example from the docs, the basic problem is the enforceability of that requirement. You can't force other callers to synchronize on the AtomicReference. You or some other developer who comes after you could easily call performSomeModification() without external synchronization.
You should make it hard to use your API incorrectly. Since AtomicReference is a generic type (AtomicReference<V>), you can enforce the synchronization in a variety of ways, depending on what V is:
If V is an interface, you could easily wrap the instance in a synchronized wrapper.
If V is a class that you can modify, you could synchronize performSomeModification(), or create a subclass in which it is synchronized. (Possibly an anonymous subclass produced by a factory method.)
If V is a class that you cannot modify, it may be difficult to wrap. In that case, you could encapsulate the AtomicReference in a class that you do control, and have that class perform the required synchronization.
Are Mutable Atomic References a Bad Idea?
Definitely not! AtomicReference is designed to provide thread-safe, atomic updates of the underlying reference. In fact, the Javadoc description of AtomicReference is:
An object reference that may be updated atomically.
So they most definitely are designed to be mutated!
Is this safe?
It depends on what you mean by "safe", and what the rest of your code is doing. There's nothing inherently unsafe about your snippet of code in isolation. It's perfectly valid, though perhaps a bit unusual, to synchronize on an AtomicReference. As a developer unfamiliar with this code, I would see the synchronization on reference and assume that it means that the underlying object may be replaced at any time, and you want to make sure your code is always operating on the "newest" reference.
The standard best practices for synchronization apply, and violating them could result in unsafe behavior. For example, since you say performSomeModification() is not thread-safe, it would be unsafe if you accessed the underlying object somewhere else without synchronizing on reference.
public void bar(AtomicReference reference) {
// no synchronization: performSomeModification could be called on the object
// at the same time another thread is executing foo()
reference.get().performSomeModification();
}
If could also be "unsafe" if your application requires that only one instance of the underlying object be operated on at any one time, and you haven't synchronized on the reference when .set()ing it:
public void makeNewFoo(AtomicReference reference) {
// no synchronication on "reference", so it may be updated by another thread
// while foo() is executing performSomeModification() on the "old" reference
SomeObject foo = new SomeObject();
reference.set(foo);
}
If you need to synchronize on the AtomicReference, do so, it's perfectly safe. But I would highly recommend adding a few code comments about why you're doing it.
I have 2 code snippets which will do the same thing which makes thread safe. first one does it using Collections.synchronizedList, Example:
DataServiceRequest request = Collections.synchronizedList(new ArrayList<DataServiceRequest>());
Second one do the same thing by synchronizing the method, Example:
public synchronized void addRequest(DataServiceRequest request) {
this.getRequests().add(request);
}
What would be the most efficient and safest way When comparing with performance from above 2 examples?
The first is really just syntactic sugar for the second (it returns a wrapper list that puts synchronized (mutex) around each call), so it is unlikely to make any difference from a performance point of view.
As for "which is the safest way" - that depends on your coding standards. You must pay attention to the documents for Collections.synchronizedList if you use it, particularly:
it is critical that all access to the backing list is accomplished through the returned list.
and
It is imperative that the user manually synchronize on the returned list when iterating over it
You'll still have the same issue when iterating a list that you control the synchronization of - this is just saying that the mutex in use for synchronizedList is the list itself. If you control the synchronization you just need to consistently use the same mutex for all thread-safe access to the backing list.
Your question might imply that you don't plan to synchronize on all list operations, not just those that change the list. If so, then this would be wrong thinking. But even if not so, using synchronizedList wrapper takes that worry away from your program because it guarantees that all method calls are synchronized.
The one thing that synchronizedList cannot guarantee is synchronization over the block of code which consumes a list iterator. This is still something you'll need to do inside your own synchronized block.
I want to access a method from within an synchronized block. Here is an example:
public void doSomething() {
// simple stuff
// a block to reduce the synchronized code to
// what really needs to be synchronized.
synchronized(this) {
if (precondition) {
doSequentialStuff();
}
}
}
private void doSequentialStuff() {
// do stuff needs to be performed sequentially.
}
To write clean code I wondered whether it would be good to make the method doSequentialStuff explicitly synchronized. IMHO this would make no difference in semantic since the lock is in both cases this and the method is guaranteed to be accessed only from the synchronized block. I hope to increase the readability.
Any advice?
Edit:
I modified the example to incorporate the comments.
If there is no legitimate code path by which doHeavyStuff may be executed without holding the lock, then by all means make it synchronized in order to preempt any future bugs introduced by an unwary developer. The readability of code can only improve what way.
It's probably better to go with an assert to check that the lock is being held. Note, you do need assertions enabled for the check to be performed.
assert Thread.holdsLock(this);
Generally if you are using this sort of private method it tends to indicate that you should split the class into two. An outer layer does the locking and perhaps other things appropriate for the client, whereas a deeper layer is more concerned with implementation.
Use of this to lock is dubious. Generally it's better to use a private explicit lock object.
Have a look at http://weblogs.java.net/blog/mason/archive/2006/09/rechecking_doub.html, it has got similar pattern covered (uses singleton as an example, but you can easily retrofit it for your case).
In a multithreaded Java application I need to iterate over a collection of objects. Since both the collection and the objects could be modified by another thread while I iterate over them, I need to use synchronization.
However nested synchronized blocks are not recommended since they could lead to deadlocks. How would I solve this problem?
Collection<Data> dataCollection = something.getDataCollection();
synchronized ( dataCollection ) {
for ( final Data data : dataCollection ) {
synchronized ( data ) {
data.doSomething(); // doSomething() changes object state
}
}
}
I think you can use CopyOnWriteArrayList instead of the outer synchronization.
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.
This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads
You can take a copy of the collection and only lock one object at a time.
Collection<Data> dataCollection = something.getDataCollection();
Collection<Data> copy;
synchronized ( dataCollection ) {
copy = new ArrayList<Data>(dataCollection);
}
for (Data data : copy) {
synchronized ( data ) {
data.doSomething(); // doSomething() changes object state
}
}
Can't believe nobody pointed out that the number one way to avoid synchronizing on the Data object is to have this object itself thread-safe! It's also the correct way of handling synchronization - if you know that your object will be accessed by multiple threads, handle synchronization the way you see fit inside the class, not in the code that may access it. You will also certainly be more efficient because you can limit synchronization to just the critical blocks, use ReadWriteLock, j.u.c.atomic, etc
Nested synchronization can lead to deadlock, but it doesn't have to. One way to avoid deadlocks is to define an order that you synchronize objects and always follow it.
If you always synchronize the dataCollection object before you synchronize the data objects, you won't deadlock.
Take a look at ReentrantReadWriteLock. With this class you can implement a lock that makes it possible for any number of non-modifying (reading) threads to access the shared property simultaneously, but only one modifying (writing) thread to access it at a time (all other readers and writers are blocked until the writing thread releases the write-lock). Remember to test your implementation thorougly, as wrong usage of the locks can still lead to race condition and/or deadlocks.
Whether you use CopyOnWriteArrayList as Bozho said or copy the list before iterating as Peter says should depend on how much you expect the list to be edited compared to iterated over.
Use CopyOnWriteArrayList when you expect the list to be iterated over far more than it is modified.
Use copying the list if you think it will be modified far more than it is iterated over.
These should be the first options because concurrency solutions should be simple unless unavoidable, but if neither situation applies you will need to pick one of the more complicated strategies outlined in the comments here.
Good luck!
I'm using Collections.synchronizedCollection in Java to protect a Set that I know is getting accessed concurrently by many threads. The Java API warns:
" It is imperative that the user manually synchronize on the returned collection when iterating over it:
Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized(c) {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
"
If I use c.contains(obj), is that thread-safe? Internally, obviously, this is iterating over the Collection and seeing if any of the objects in it are equal to obj. My instinct is to assume that this is probably synchronized (it would seem to be a major failing if not), but given previous pains with synchronization, it seems wise to double-check, and a Google search for answers on this hasn't turned up anything.
In itself, a call to contains is safe.
The problem is that one often tests whether a collection contains an element then does something to the collection based on the result.
Most likely, the test and the action should be treated as a single, atomic operation. In that case, a lock on the collection should be obtained, and both operations should be performed in the synchronized block.
Collections.synchronizedCollection() will return a thread safe collection which means
any single method call is thread safe by itself. It depends what you want do. If you want to call couple of methods, java cannot make it thread safe together.
It's safe, because contains itself is synchronized.