I am working on an app for the J2ME and sometime it freezes completely and it takes quite some time for the AMS to close it. It seems to me like a dead-lock issue.
Could you advise me as to what could cause dead locks? Would, for instance, calling a synchronized method of a object cause dead lock if it calls another synchronized method of its own?
Thanks!
Update
Am I right in saying that a deadlock is supposed to happen in the following case:
Object P calls a synch method of object A, that calls a synch method of object B, that calls a synch method of object A
Sorry if it looks stupid of me, most probably it is. But that's why I'm asking. Thanks!
Deadlock in java is a programming situation where two or more threads are blocked forever. Java deadlock situation arises with at least two threads and two or more resources.
Deadlock occurs when a set of processes are in a wait state, because each process is waiting for a resource that is held by some other waiting process. Therefore, all deadlocks involve conflicting resource needs by two or more processes.
Two processes competing for two resources in opposite order. A single process goes through. The later process has to wait. A deadlock occurs when the first process locks the first resource at the same time as the second process locks the second resource.
A deadlock occurs when two or more threads in the JVM form a cyclic dependency with each other. In this illustration 'thread 2' is in a wait state, waiting on Resource A owned by 'thread 1', while 'thread 1' is in a wait state, waiting on Resource B owned by 'thread 2'.
Would, for instance, calling a synchronized method of a object cause dead lock if it calls another synchronized method of its own?
No, because synchronized
locks in Java are reentrant: you can acquire the same lock from the same thread multiple times without a problem.
A deadlock occurs e.g. when thread A holds lock L and tries to acquire lock M, while thread B holds lock M and tries to acquire lock L. Thus both threads are waiting for a lock held by the other, and can not progress to release their own lock. This causes both threads to wait forever. The situation may be involving more than 2 threads as well.
Deadlocks can be very difficult to detect, so the typical way is to try to avoid them by careful design. The simplest means to achieve this is to ensure that any thread which is to acquire multiple locks, acquires them always in the same predefined global order. E.g. if in the above example both threads A and B attempt to acquire lock L first, then lock M, there will be no deadlock.
Your issue may be caused by other things than a deadlock too, e.g. a livelock (when a thread, while not blocked, still can't progress because it keeps retrying an operation that always fails).
With Java intrinsic locks (i.e. synchronized
blocks), the underlying Lock
object itself is not visible in the code, only the object we are locking on. Consider
class MyClass {
private Object object = new Object();
public synchronized void synchronizedOnThis1() {
...
}
public void synchronizedOnThis2() {
synchronized(this) {
...
}
}
public void synchronizedOnPrivateObject() {
synchronized(object) {
...
}
}
}
class ExternalParty {
public void messUpLocks() {
final MyClass myObject = new MyClass();
synchronized(myObject) {
Thread otherThread = new Thread() {
public void run() {
myObject.synchronizedOnThis1();
}
};
otherThread.start();
// do a lengthy calculation - this will block the other thread
}
}
}
Both the synchronizedOnThis*
methods are synchronized on the containing MyClass
instance; the synchronization of the two methods is equivalent. However, the class instance is obviously accessible to the outside world, so an external party can use it as a lock from outside the class, as shown above. And if the object is accessible from another thread, and that thread calls one of its synchronizedOnThis*
methods, that call will block as long as this thread is within the synchronized(myObject)
block.
OTOH the method synchronizedOnPrivateObject
uses a private object as lock. If that object is not published to external parties in any way, noone else can (inadvertently or malevolently) cause a deadlock involving this lock.
Most probable reason would be two threads trying to obtain locks to two objects. Thread 1 locks A and is waiting for B, but thread 2 locks B and is waiting for A. Both threads end up waiting forever for objects which will never be released.
There is no quick solution except make sure your code does things in a very well defined order. As a general rule, the synchronized block should be as small as possible, usually on a specific object than on a method. Put a lot of logging in and see if you can figure out if something like this is happening.
Java 5 has explicit Lock objects which allow a finer grained control including timeouts over simple synchronized blocks but I do not know if they would be useful for J2ME. There is a backport of the Java 5 concurrency libs which it may be possible to get working with J2ME - http://backport-jsr166.sourceforge.net/ if this issue is sufficiently large to merit using them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With