We're calling "lock()" on a ReentrantLock and threads are getting stuck there when they apparently shouldn't.
When debugging with a breakpoint just before the call to "lock()", the first thread would stop there with the program pointer going to "Thread.exit()".
The lock object's toString() says "unlocked" and it's "state" attribute is "0".
The behavior is not always the same. Sometimes the first thread goes past the lock as expected.
userLock.lock(); //first thread sometimes gets stuck here (and the following ones as well)
//"userLock" has "state=0" and toString() says "UNLOCKED"
try {
Transaction tr = HibernateConfig.getSessionFactory().getCurrentSession().beginTransaction();
try {
execute();
tr.commit();
} catch (ConstraintViolationException e) {
//probably traces with repeated time
System.err.println(e.getMessage());
if (tr.isActive()) {
tr.rollback();
}
} catch (RuntimeException e) {
e.printStackTrace();
if (tr.isActive()) {
tr.rollback();
}
}
} catch (Throwable e) {
e.printStackTrace();
} finally {
userLock.unlock();
}
try to put a breakpoint after userLock.lock(); then you should get the thread, that gets the lock.
alternatively you could use userLock.getOwner(); right behind .lock() to see wich thread got the lock.
The problem was my breakpoint was not before "lock()" like I said, but on it.
What happened is a bunch of threads would be blocked in that line by the breakpoint, one of them would still acquire the lock, and then the debugger would give me control over a random one of them which hadn't acquired the lock. And I was failing to check every thread blocked by the breakpoint to find the free one.
In the end I put the breakpoint actually before the lock and it behaved as expected.
This was confusing and I hope the question will still help someone.
Note: I'm still confused by the fact the lock's state said "unlocked" in the debugger while I was controlling a locked thread.
Related
Occasionally the system throws a SEVERE error on the synchronized block and there is a try-catch which should, in theory, initiate a thread 'unlock' process however this isn't triggered. I, therefore, can conclude that this is not treated as an exception within the system. Is there a reasonable way of handling said lock?
Consider the following code from board.jsp:
account = Account.get(accountID);
Object synch=account;
if(synch == null) {
%>No account.<%
return;
}
try {
synchronized(synch) {
....
}
} catch (Exception e) {
....
} finally {
....
}
example dump
SEVERE: Scheduled tasks not running!
Apr 07, 2020 4:59:36 PM ExecLauncher:execLauncher run
SEVERE: ---------------------
Thread is: "http-bio-8080-exec-18" Id=122 BLOCKED on com.main.Account#5a0b8133 owned by "http-bio-8080-exec-7" Id=38
at org.apache.jsp.realtime.board_jsp._jspService(board_jsp.java:192)
- blocked on com.main.Account#5a0b8133
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
Thanks for looking :)
You can try this out, you will get more control to lock and unlock explicitly using Reentrant locks.
account = Account.get(accountID);
Object synch=account;
Lock lock = new ReentrantLock();
if(synch == null) {
%>No account.<%
return;
}
try {
lock.lock();
/* Your actual code which you were executing in
the synchronized block */
} catch (Exception e) {
....
} finally {
lock.unlock(); // this will work
}
This is not an exception but rather it says that the Thread "http-bio-8080-exec-18" can not execute because it tries to enter the synchronized(synch) block. It can not enter this block because the monitor is currently held by the thread "http-bio-8080-exec-7".
So the first thing is to find out why "http-bio-8080-exec-7" does not release the monitor. This might simply be a performance problem, to many threads are trying to execute tissecition in parallel. Or the thread might be hanging. You can analyze this by generating a thread dump:
To generate a thread dump go to the bin folder of your java installation. There is a tool called jps (jps.exe on windows) Execute this, you will see a number (the pid) and a name of a program. Find your program and execute jstack [pid]. jstack is also in the bin folder of your Java installation.
You then will see what every thread is doing in your program, and what the thread with is currently owning the monitor is doing.
There is a way to wait only a specific time to try to aqcuire a lock. I am not quite sure if this solves your problem but to be complete here it is. Use a reentrant lock together with tryLock:
if( lock.tryLock(long timeout,
TimeUnit unit))
{ try {
// ... method body
}
finally {
lock.unlock()
}
}
else {
// lock could not be acquired at the given time
}
As the title suggested, I have some code wrapped in a while(true) infinite loop, and all of them are fully caught by try and catch block. This thread is started in the main method, however, after long run, this worker thread is vanished mysteriously when I check using the jstack and causing work accumulated.
Below is my code:
public void run() {
while (true) {
try {
// Consumer consumes from Kafka server
Global.KAFKA_METRIC_DATA_CONSUMER.consume(topic, handler);
} catch (Exception e) {
logger.error("Kafka consumer process was interrupted by exception!");
} finally {
try {
// Prevent restart too often
Thread.sleep(30 * BaseConst.SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
For my understanding, this structure will keep the thread running so is the consumer. Even if the consume() methods failed, it will restart infinitely. However, as I mentioned above, the whole thread disappear silently without any error log. Could anyone provide some clue please?
Some more information that might be helpful:
I have checked the consume method will never shutdown the consumer
nor close the socket to the server. It will continuously try to
connect server after fail.
I analysed the java heap dump, and I found there is a memory leak
somewhere else in the project, causing memory occupation extremely
high and the gc very often. However, the main method is still
running.
OutOfMemoryError is not an Exception. It's an Error derived from Throwable.
If that was thrown somewhere in your consume(topic, handler), finally would still be called, delaying the inevitable some 30s... but after that the error would be passed upward and your loop would be terminated.
You are catching Exception so there's a chance that a java.lang.Error or a java.lang.Throwable is being thrown (eg OutOfMemoryError)
If you really want to catch everything, you'll need to catch Throwable and not just Exception subclasses.
Your thread is probably killed by an error.
An error is not an exception! But they both extend Throwable
Add another catch block that catches errors.
Throwable should never be caught, because errors require a different handling than exceptions
I am trying to terminate the thread in the following code:
public synchronized void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
this.scan();
this.distribute();
this.wait();
}
} catch (InterruptedException e) {}
}
public void cancel() {
this.interrupt();
}
But the thread won't terminate. I used the debugger and found out that after the command this.interrupt(), the thread doesn't get interrupted (I put a watch on the expression this.isInterrupted() and it stays false). Anyone has an idea why this thread won't get interrupted?
Edit:
The problem has been found. Turns out that there were two instances of this thread. I am attaching the problematic code that lead to this:
/* (class Detector extends Thread) */
Detector detector = new Detector(board);
...
Thread tdetector = new Thread(detector); /* WRONG!!! */
...
tdetector.start();
...
According to the docs, if you call interrupt() while the thread is in a wait() state, the interrupt flag will not be set. You should be getting an interrupted exception, which will exit the loop (and the thread).
EDIT
Per my comment and your response, the problem is that you have more than one of these threads running.
You are probably calling cancel on the wrong thread. If you look at it, it cancel() cancels this thread. You probably want to cancel some other thread.
It is also true that your call to isInterrupted() is unnecessary, but that won't cause interrupts to be lost ...
On the other hand, if the cancel method is a method of a class that extends Thread, then the this could be the thread that needs cancelling. (The problem for us folks trying to answer is that there is/was insufficient detail in the original question ...)
I am running a thread whose main action is to call on a proxy using a blocking function , and wait for it to give it something.
I've used the known pattern of a volatile boolean and the Interruption , but I'm not sure it will work: When I tried to add a catch block for InterruptedException , I get the error:
Unreachable catch block for InterruptedException. This exception is never thrown from the try statement body
So if I'm never going to get anInterruptedException, this means I'll never get out of the blocking action - thus will never stop.
I'm a bit puzzled. Any idea?
public void run() {
Proxy proxy = ProxyFactory.generateProxy();
Source source;
while (!isStopped) {
try {
source = proxy.getPendingSources();
scheduleSource(source);
} catch (Exception e) {
log.error("UnExpected Exception caught while running",e);
}
}
}
public void stop() {
this.isStopped = true;
Thread.currentThread().interrupt();
}
First, you don't really need a separate flag (if you do, use an AtomicBoolean), just check Thread.currentThread().isInterrupted() as your while condition.
Second, your stop method won't work because it won't interrupt the correct thread. If another thread calls stop, the code uses Thread.currentThread() which means the calling thread will be interrupted, not the running one.
Finally, what is the blocking method? Is it scheduleSource()? If that method doesn't throw InterruptedException, you won't be able to catch it.
Try the following:
private final AtomicReference<Thread> currentThread = new AtomicReference<Thread>();
public void run() {
Proxy proxy = ProxyFactory.generateProxy();
Source source;
currentThread.set(Thread.currentThread());
while (!Thread.currentThread().isInterrupted()) {
try {
source = proxy.getPendingSources();
scheduleSource(source);
} catch (Exception e) {
log.error("UnExpected Exception caught while running", e);
}
}
}
public void stop() {
currentThread.get().interrupt();
}
Only a few, well-defined "blocking methods" are interruptible. If a thread is interrupted, a flag is set, but nothing else will happen until the thread reaches one of these well-defined interruption points.
For example, read() and write() calls are interruptible if they are invoked on streams created with a InterruptibleChannel. If a Socket is used as the starting point, calling interrupt() on a Thread blocked in the read has no effect. Note that if a blocking I/O operation is interrupted successfully, the underlying channel is closed.
Another large class of interruptible operations are those thrown by various blocking operations on classes in the java.util.concurrent packages. Of course, the original wait() method is interruptible as well.
Blocking methods can be identified by looking for a throws InterruptedException in their method signatures. They should be well-documented too, to describe any side-effects of interruption.
You can write an interruptible method of your own, but it has to be composed of interruptible lower-level operations itself.
ok, people, don't kill me over this.
I experimented with Thread.stop() for fun, to kick thread out of a blocking action, catch ThreadDeath, keep target thread alive, and move on.
It seems working. The world isn't ending. But I'm just saying. You are responsible for you own doing. Why am I rapping?
You stop method is calling interrupt on the wrong thread. Thread.currentThread() is the thread that is interrupting, not being interrupted.
How are you calling stop from the executing thread?
If you call stop() from another thread, you'll kill it, not the thread running in the try/catch block.
I have the following code in a Runnable that gets passed to a thread t:
public void run() {
logger.debug("Starting thread " + Thread.currentThread());
try {
doStuff();
} catch (Exception e) {
logger.debug("Exception in Thread " + Thread.currentThread());
}
logger.debug("End of thread " + Thread.currentThread());
}
I've hit a bug where I see deadlock with the following conditions
only the start of thread message has been printed by my logs
A thread dump shows that the thread t (supposed to be executing this) is no longer running
Is there some magical way this thread could have terminated early without either logging an end of thread message OR throwing an exception?
Are you sure that doStuff() did not throw an Error? Change catch (Exception e) to catch (Throwable t). It's possible to kill threads in Java with Thread.stop(), but that is highly unlikely.
Are you sure that where you start() the Thread, you also join() it afterwards?
Runnable myRunnable=new Runnable(){
#Override
public void run(){
// your original code goes here
}
};
Thread myThread=new Thread(myRunnable);
myThread.start();
myThread.join(); // magic happens here! it waits for the thread to finish ;)
By the way, join() may throw an InterruptedException,
so if something interrupts your thread while it's running,
join will inform you about this by throwing this exception.
Hope this helps.
When you catch Exception, you will catch any RunnableException and any declared thrown Exception, but you will not catch anything that extends Error. If you truly want to catch anything, then you need to catch Throwable.
If you want to do this for logging purposes only and you don't care why the Thread exits, you can do this:
public void run() {
logger.debug("Starting thread " + Thread.currentThread());
try {
// The work of your Thread
} finally {
logger.debug("End of thread " + Thread.currentThread());
}
}
and the finally statement is guaranteed to execute unless the Thread is stopped or deadlocks or in some other way stops executing without an Exception.
In most of my programs, I install an UncaughtExceptionHandler so that I'll know about every Thread that dies unexpectedly. It's been a tremendous help in tracking failures. This was added to the language as of Java 5.
Sure, the thread could get interrupted after the end of the try/catch block but before the last logger.debug statement. In that case it would throw an InterruptedException that, in principle, might not get recorded anywhere (if the default exception handler is set to ignore such things).
That seems like a rather unlikely scenario, though... it's kind of hard to tell what's going on without knowing more about the rest of your program, though.
When ever you trap a general exception I suggest you log it so you know what the exception was and it cause. Failing to do so will not help you at all.