About multithreading

4

418928

Hi everybody,

I'd like to know if there is any way to know which execution thread
holds a lock. That is, I would like to know, before a block
synchronized(o), if any other thread holds the lock to o (for
debugging, for example, because I think that no other thread should
have the lock at that moment). I think it's not possible, not even with
the new ReentrantLocks, but just in case you may have any suggestion to
debug these kind of things...

Also, I have another question. A few years ago, I read that the
interpretation of the "volatile" keyword was optional. Therefore, when
I wanted to read a variable that another thread could write, I always
used synchronized methods. It is my feeling now that "volatile" is
never ignored... anyone could confirm this? Specifying volatile would
be more efficient than serializing some methods I have.

Thanks in advance,

S.
 
T

Thomas Hawtin

Hi everybody,

I'd like to know if there is any way to know which execution thread
holds a lock. That is, I would like to know, before a block
synchronized(o), if any other thread holds the lock to o (for
debugging, for example, because I think that no other thread should
have the lock at that moment). I think it's not possible, not even with
the new ReentrantLocks, but just in case you may have any suggestion to
debug these kind of things...

In 1.6 you can use JMX.

http://jroller.com/page/tackline?entry=detecting_invokeandwait_abuse

You could probably use the debugging interface for old JVMs, but it'd be
some work.

The point of "synchronized" is that other threads may be holding the
lock, so I'm not entirely sure what you aim is here.
Also, I have another question. A few years ago, I read that the
interpretation of the "volatile" keyword was optional. Therefore, when
I wanted to read a variable that another thread could write, I always
used synchronized methods. It is my feeling now that "volatile" is
never ignored... anyone could confirm this? Specifying volatile would
be more efficient than serializing some methods I have.

Before 1.4 (in Sun's JVMs) volatile was not implemented. It should work
in 1.4+ with the new Java Memory Model (JMM) semantics. The old
semantics were not particularly useful. I'd suggest staying away from it
unless you really need it. Indeed stay away from synchronized and use
java.util.concurrent.

Tom Hawtin
 
E

Eric Sosman

Hi everybody,

I'd like to know if there is any way to know which execution thread
holds a lock.

synchronized(obj) {
System.out.println(Thread.currentThread()
+ " holds the lock on " + obj);
}

Not very useful for your purposes, but I think that's the
only reliable way ...

The problem with "Who owns the lock?" queries is that
the result can be out of date before you can use it. All
you could really get (and I don't know whether even this
much is Javapossible) is "Who owned the lock a moment ago?"
This tells you very little about who owns the lock now
(for some definition of "now"), or about how many times the
lock has been taken and released since you asked about it.

There might be a way to find out whether the current
thread does or doesn't hold a particular lock, and that
result would be "stable:" if you don't seize or release the
lock between the moment of the query and the moment you
make a decision based on it, the result remains valid. And
if the result happens to be "I've got it," you know that no
other thread has it. But if the result is "No, not mine"
then there's nothing you can conclude about the state of
the other threads in the program.
That is, I would like to know, before a block
synchronized(o), if any other thread holds the lock to o (for
debugging, for example, because I think that no other thread should
have the lock at that moment). I think it's not possible, not even with
the new ReentrantLocks, but just in case you may have any suggestion to
debug these kind of things...

You could (hypothetically) check a lock and find that
nobody owned it, but that still wouldn't tell you much about
the correctness of the program. It's not a matter of whether
the lock is or isn't held at a moment when you think it should
be free, but of whether there's a path by which another thread
*can* attempt to take the lock when it shouldn't. Poor analogy:
If you never look at the traffic signals, the fact that the
light happens to be green when you drive through the intersection
doesn't mean you're driving correctly.
 
R

Robert Klemme

I'd like to know if there is any way to know which execution thread
holds a lock. That is, I would like to know, before a block
synchronized(o), if any other thread holds the lock to o (for
debugging, for example, because I think that no other thread should
have the lock at that moment). I think it's not possible, not even with
the new ReentrantLocks, but just in case you may have any suggestion to
debug these kind of things...

Modern IDE's can typically tell you that while debugging. At least
Eclipse is capable of doing that.
Also, I have another question. A few years ago, I read that the
interpretation of the "volatile" keyword was optional. Therefore, when
I wanted to read a variable that another thread could write, I always
used synchronized methods. It is my feeling now that "volatile" is
never ignored... anyone could confirm this? Specifying volatile would
be more efficient than serializing some methods I have.

Personally I would take a conservative approach and use "synchronized".
If that proves to be too slow, I would change it later. But keep in
mind that the overhead of "synchronized" on modern VM's has significant
decreased vs. older versions of Java.

Kind regards

robert
 
C

Chris Uppal

Eric said:
synchronized(obj) {
System.out.println(Thread.currentThread()
+ " holds the lock on " + obj);
}

You can do a little better than that with the static Thread.holdsLock() method.
That is still only of very limited use.

-- chris
 
T

Thomas Hawtin

I'd like to know if there is any way to know which execution thread
holds a lock. That is, I would like to know, before a block
synchronized(o), if any other thread holds the lock to o (for
debugging, for example, because I think that no other thread should
have the lock at that moment). I think it's not possible, not even with
the new ReentrantLocks, but just in case you may have any suggestion to
debug these kind of things...

It just occurred to me that you can get hold of the owner thread for
ReentrantLocks, as it does have the thread handling structure available
at the Java level. Use getOwner(), either by subclassing or reflection
with setAccessible. Just to see a any thread holds the lock, then there
is ReentrantLock.isLocked(). Even for a Lock, to see if another thread
holds the lock, you could do:

final boolean otherHasLock;
if (lock.tryLock()) {
lock.unlock(); // Look! No try-finally.
otherHasLock = false;
} else {
otherHasLock = true;
}

(Note the note on ReentrantLock.isLocked(): "This method is designed for
use in monitoring of the system state, not for synchronization control.")

Tom Hawtin
 
E

Eric Sosman

Chris Uppal wrote On 11/03/06 06:30,:
Eric Sosman wrote:




You can do a little better than that with the static Thread.holdsLock() method.
That is still only of very limited use.

It answers the question "Does the current thread hold
the lock?" but the O.P. was asking the harder question "What
thread holds the lock?" My tongue-in-cheek answer (and the
longer explanation that accompanied it) was intended to show
that the question can't have a useful answer (in a running
program; studying a post-mortem dump or a program that's
halted under debugger control is another matter).

I imagine this is what you mean by "very limited use." A
thread cannot reliably detect the state of a shared object[*]
unless it holds the object's lock[**], so "locked by thread T1"
is something thread T2 cannot detect.

[*] The state of a shared immutable value object can be
detected without a lock. However, synchronizing on an object
changes the object's state (from unlocked to locked), and so
in a weak sense "mutates" the object; an object subject to
synchronization is not strictly "immutable."

[**] Or whatever lock or combination of locks the program
uses to guard the object; for example, an object might be
protected not by its own lock, but by a lock on a Collection
that holds it.
 
D

Daniel Pitts

Thomas said:
It just occurred to me that you can get hold of the owner thread for
ReentrantLocks, as it does have the thread handling structure available
at the Java level. Use getOwner(), either by subclassing or reflection
with setAccessible. Just to see a any thread holds the lock, then there
is ReentrantLock.isLocked(). Even for a Lock, to see if another thread
holds the lock, you could do:

final boolean otherHasLock;
if (lock.tryLock()) {
lock.unlock(); // Look! No try-finally.
otherHasLock = false;
} else {
otherHasLock = true;
}

(Note the note on ReentrantLock.isLocked(): "This method is designed for
use in monitoring of the system state, not for synchronization control.")

Tom Hawtin
Actually, I would guess that the OP's real problem wouldn't need an
"lock.unlock()". They probably have a deadlock issue, and are trying
to debug it. I can't be sure though.

The OP might have been better to ask the question "Is there a way in
any debugger to see which thread owns a specific object's monitor?".
 
T

Thomas Hawtin

Daniel said:
Actually, I would guess that the OP's real problem wouldn't need an
"lock.unlock()". They probably have a deadlock issue, and are trying
to debug it. I can't be sure though.

If you've got a dealock, then ctrl-\ (or ctrl-break if for some reason
you are forced to use Windows). In 1.6 that even detects
java.util.concurrent.lock deadlocks.

Tom Hawtin
 
P

Piotr Kobzda

Thomas said:
In 1.6 you can use JMX.

Unfortunately, even in 1.6 you can't always guess which execution thread
holds a lock. The problem is in lock object identity offered with JMX
management classes. LockInfo can tell us only what is the
identity-hash-code and a class name of locked monitor/synchronizer
object, not a lock object itself. As the result it is not always safe
to say that a given lock object is actually the same object as the one
identified by LockInfo.


piotr
 
P

Piotr Kobzda

Piotr said:
Unfortunately, even in 1.6 you can't always guess which execution thread
holds a lock. The problem is in lock object identity offered with JMX
management classes. LockInfo can tell us only what is the
identity-hash-code and a class name of locked monitor/synchronizer
object, not a lock object itself. As the result it is not always safe
to say that a given lock object is actually the same object as the one
identified by LockInfo.

One workaround for mentioned possible ambiguity in lock object identity
is attached below (not tested intensively!).

It tries to acquire a lock on a given object, and than, in a case when a
lock acquiring thread is blocked, makes a use of JMX's ThreadInfo to
find a thread which holds this lock.

It's currently implemented to detect monitor locks only (which seems to
work fine in both 1.5 and 1.6) -- synchronizers locks detection
(supported only with JMX in 1.6) is left for the reader. :)


piotr


==== Locks.java ====

import java.lang.management.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;

public class Locks {

static final ThreadMXBean threadMXBean
= ManagementFactory.getThreadMXBean();

private static ExecutorService taskExecutor
= Executors.newCachedThreadPool(new ThreadFactory() {

AtomicLong count = new AtomicLong();

public Thread newThread(Runnable r) {
Thread t = new Thread(r,
"locks-pool-thread-"
+ count.incrementAndGet());
t.setDaemon(true);
return t;
}

});


public static Thread lockOwner(final Object lock) {
final ReentrantLock taskLock = new ReentrantLock();
final Condition taskSync = taskLock.newCondition();

class Task implements Runnable {
volatile long threadId = -1;

public void run() {
taskLock.lock();
try {
threadId = Thread.currentThread().getId();
taskSync.signal();
} finally {
taskLock.unlock();
}
// acquire a lock
synchronized (lock) {}
}
};

taskLock.lock();
try {
Task task = new Task();
Future<?> future = taskExecutor.submit(task);

while (task.threadId == -1 && !future.isDone()) {
try {
taskSync.await();
} catch (InterruptedException ignore) {}
}

while(task.threadId != -1 && !future.isDone()) {
ThreadInfo ti = threadMXBean
.getThreadInfo(task.threadId);
if (ti == null)
break; // task died
long lockOwnerId = ti.getLockOwnerId();
if (lockOwnerId != -1) {
future.cancel(true);
return threadForId(lockOwnerId);
}
}
} finally {
taskLock.unlock();
}
return null;
}

private static Thread threadForId(long threadId) {
Thread[] threads = new Thread[Thread.activeCount()];
Thread.enumerate(threads);
for(Thread t : threads)
if (t != null && t.getId() == threadId)
return t;
return null;
}

}
 
C

Chris Uppal

Eric said:
I imagine this is what you mean by "very limited use." A
thread cannot reliably detect the state of a shared object[*]
unless it holds the object's lock[**], so "locked by thread T1"
is something thread T2 cannot detect.

I think that's pretty much what I had in mind. I'd have put it differently
though. More like:

The only use for Thread.holdsLock() is as a debugging facility
to detect misuses of code which is not itself synchronised, but
which expects always to be called from a syncronised contex.

I supose there /might/ be other uses but I can't think of any valid ones/

-- chris
 
P

Piotr Kobzda

Piotr said:
It tries to acquire a lock on a given object, and than, in a case when a
lock acquiring thread is blocked, makes a use of JMX's ThreadInfo to
find a thread which holds this lock.

Unfortunately again, it introduces a new problem (beside of "mutability"
and "usefulness" problems mentioned by Eric earlier).

Now each thread waiting to acquire a lock (in the Executor's thread
pool) can not be easily canceled.

This is because a thread waiting for monitor on synchronized statement
is not interruptible using its associated Future.cancel() method. It
can not be even canceled using deprecated Thread.stop().

As a result all new threads might remain alive long time (including
infinity) before acquiring a lock, which in turn might result in a lot
of unwanted threads in pool.


This shows important advantage of Doug Lea's Locks over classic Java
monitors -- locks implementing java.util.concurrent.Lock can be acquired
interruptibly. However, there is allowed to change a default locks
semantics in implementation, which makes proposed method generally
useless for this kind of locks too.


So now it seems also to me, there is no general and nice way (unless
some additional assumptions will be provided) to know which thread holds
a lock for any given object.


piotr
 
P

Piotr Kobzda

Piotr said:
Thomas Hawtin wrote:

Unfortunately, even in 1.6 you can't always guess which execution thread
holds a lock. The problem is in lock object identity offered with JMX
management classes. LockInfo can tell us only what is the
identity-hash-code and a class name of locked monitor/synchronizer
object, not a lock object itself. As the result it is not always safe
to say that a given lock object is actually the same object as the one
identified by LockInfo.

To measure somehow this ambiguity in identity, I wrote this:

Object o1 = new Object(), o2 = new Object();
long count = 0;
while(o2.hashCode() != o1.hashCode() && ++count != 0)
o2 = new Object();
System.out.printf("%s\n%s\n%d\n", o1, o2, count);


On my machine it prints out the following:

java.lang.Object@187aeca
java.lang.Object@187aeca
6241753

[ results vary depending on the JVM implementation and a heap size
related options ]


It proves to me that there is a real danger in having two distinct
objects with same identity-hash-code and class-name on same time.


Now I wonder why a lock object itself is not referenced (e.g. weakly) by
a LockInfo class?
The same question might be widened to a ThreadInfo and other ...Info
classes.

The JMX would be more powerful with such references present.


BTW -- In 1.6 during creation of a ThreadInfo true monitor/synchronizer
objects are passed by the JVM to this constructor:

private ThreadInfo(Thread t, int state, Object lockObj, Thread
lockOwner,
long blockedCount, long blockedTime,
long waitedCount, long waitedTime,
StackTraceElement[] stackTrace,
Object[] monitors,
int[] stackDepths,
Object[] synchronizers)


So if for debugging purposes we are interested in a monitors (or any
synchronizers -- not a ReentrantLock only) lock owner detection, we can
create our own version of ThreadInfo class, which will assign true
object reference with a LockInfo (and MonitorInfo) instances it creates.
And than, after adding our modified ThreadInfo (possibly with a few
additional classed) as a first entry in the bootstrap classpath, the JVM
we will give us all information we need for certain locks identity.

Example code supporting this extended usage scenario is attached below.

It checks if a provided LockInfo implements the following simple interface:

public interface LockReference {
Object getLock();
}

if so, it uses the result of getLock() in comparison with a lock
candidate. Otherwise, it prints a warning message (see sameIdentity()
implementation).


piotr


==== Locks16.java ====

import java.lang.management.*;
import java.util.*;

public class Locks16 {

static final ThreadMXBean threadMXBean
= ManagementFactory.getThreadMXBean();

public static Thread monitorLockOwner(Object lock) {
for(ThreadInfo ti :
threadMXBean.getThreadInfo(
threadMXBean.getAllThreadIds(), true, false)) {
for(MonitorInfo li : ti.getLockedMonitors())
if (sameIdentity(li, lock))
return threadForId(ti.getThreadId());
}
return null;
}

public static Thread synchronizerLockOwner(Object lock) {
for(ThreadInfo ti :
threadMXBean.getThreadInfo(
threadMXBean.getAllThreadIds(), false, true)) {
for(LockInfo li : ti.getLockedSynchronizers())
if (sameIdentity(li, lock))
return threadForId(ti.getThreadId());
}
return null;
}

public static Thread[] blockedWaitingThreads(Object lock) {
List<Thread> threads = new ArrayList<Thread>();
for(ThreadInfo ti :
threadMXBean.getThreadInfo(
threadMXBean.getAllThreadIds(), false, false)) {
LockInfo li = ti.getLockInfo();
if (li != null && sameIdentity(li, lock))
threads.add(threadForId(ti.getThreadId()));
}
return threads.toArray(new Thread[threads.size()]);
}

private static boolean sameIdentity(LockInfo li, Object lock) {
if (li.getIdentityHashCode() == System.identityHashCode(lock)
&& li.getClassName().equals(lock.getClass().getName())) {
if (li instanceof LockReference)
return ((LockReference)li).getLock() == lock;
System.err.println("#warning: possible " +
"ambiguity in detected lock " + lock + " identity");
return true;
}
return false;
}

private static Thread threadForId(long threadId) {
Thread[] threads = new Thread[Thread.activeCount()];
Thread.enumerate(threads);
for(Thread t : threads)
if (t != null && t.getId() == threadId)
return t;
return null;
}


/**
* Test
* @param args
*/
public static void main(String[] args) throws Exception {
final Object lock = new Object();

Thread checker = new Thread() {
public void run() {
while(true) {
System.out.println("lock owner: "
+ monitorLockOwner(lock));
System.out.println("blocked threads: "
+
Arrays.toString(blockedWaitingThreads(lock)));
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {}
}
}
};
checker.setDaemon(true);
checker.start();

Thread.sleep(2000);

for(int i = 1; i <= 10; ++i) {
Thread locker = new Thread("#" + i) {
public void run() {
try {
synchronized(lock) {
System.out.println(this + " entered monitor");
Thread.sleep(1000);
}
} catch (InterruptedException ignore) {
} finally {
System.out.println(this + " left monitor");
}
};
};
locker.setDaemon(true);
locker.start();
}

Thread.sleep(12000);
}

}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top