Simple thread crashes Android app - java

I found a very peculiar issue when creating an launching a thread inside an Android app.
If I have the following class thread:
public class TroubleThread extends Thread{
boolean running;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
while (isRunning()){
}//end while
}//end run
}
and add it somewhere in the Activity's onCreate(...) method like:
public class MyActivity extends Activity {
TroubleThread myThread;
#Override
public void onCreate(Bundle savedInstanceState) {
//....
myThread = new TroubleThread();
myThread.setRunning(true);
myThread.start();
}
}
the app will crash.
But if I change the run() method to:
#Override
public void run() {
while (running){ //NOTE THE USE OF DIRECT FIELD ACCESS INSTEAD OF METHOD
}//end while
}//end run
it stops from crashing.
Even if I solved my problem by using locks, notify() and wait() the question still remains:
Why when using direct access to the field the app continues to work while when using the method it crashes?

First of all, since you did not provide a MCVE, other people cannot reproduce your problem. That is unfortunate because it means we cannot be sure what the real cause of the problem is. We can only propose hypotheses.
Some people have hypothesized that your problem is due to something else; e.g. an infinite loop on the GUI thread. That is plausible, but there is no clear evidence for this. (And we can't see the code ....)
My hypothesis is that this is a "memory visibility" issue. The Java Language Specification has a chapter that defines the circumstances under which one thread is guaranteed to see a value written to memory by another thread. The rules are rather complicated and technical, but the essence is that you need to analyzing whether there is a happens before relationship between a memory write by one thread and a subsequent memory read by another thread. A number of things will give you that relationship:
the threads write / reading a shared volatile variable
the threads synchronizing using the same lock
a thread start
a thread join
completion of a constructor (for final variables)
However, none of these things exist in your program with respect to the running variable. This means that there is no guarantee that the thread that is looping on the running variable will see the results of the setRunning call made by the other thread:
It might see the changes immediately
It might see the changes later
It might never see them
All three behaviors are possible .... in the absence of a happens before relationship.
So why does one version of the code behave differently to the other?
We can't be sure. To actually be sure, someone would need to do a deep analysis of the native (machine) code for your example. It could be something to do with (legal) reordering that the optimizer has done in one case and not the other. It could be a subtle timing effect.
But either way, the JLS says the the compiler is not obliged to make sure that the write is visible. Why? Because this code breaks the rules of the memory model.
Solutions:
In this case, the simplest solution is to declare running as volatile.
Another solution is to declare isRunning() and setRunning as synchronized methods.
Either of these are sufficient to provide the happens before relationship ... and guarantee that isRunning() sees the update made by setRunning().

Related

Do I have to use synchronized on main thread methods?

To be more specific my question is if the main thread methods are already synchronized?
For example:
#MainThread
class MyClass{
private Object o = null;
#MainThread
MyClass(){
}
#MainThread
public Object getObjectFromMainThread(){
return this.o.getObj2();
}
#MainThread
public void setObjectFromMainThread(Object obj){
obj.set(1);
this.o=obj;
}
#AnyThread
public synchronized Object getObjectFromAnyThread(){
return this.o;
}
#AnyThread
public synchronized void setObjectFromAnyThread(Object obj){
this.o=obj;
}
}
The methods getObjectFromMainThread and setObjectFromMainThread which are called only from main thread are not synchronized. Does it need to be synchronize as well or is not necessary?
The answer to your immediate question is yes, you will have to synchronize the getObjectFromMainThread and setObjectFromMainThread methods in your example. The answer to why there's this need is a mighty deep rabbit hole.
The general problem with multithreading is what happens when multiple threads access shared, mutable state. In this case, the shared, mutable state is this.o. It doesn't matter whether any of the threads involved is the main thread, it's a general problem that arises when more than one thread is in play.
The problem we're dealing with comes down to "what happens when a thread is reading the state at the same time that one or more threads are writing it?", with all its variations. This problem fans out into really intricate subproblems like each processor core having its own copy of the object in its own processor cache.
The only way of handling this is to make explicit what will happen. The synchronized mechanism is one such way. Synchronization involves a lock, when you use a synchronised method, the lock is this:
public synchronized void foo() {
// this code uses the same lock...
}
public void bar() {
synchronized (this) {
// ...as this code
}
}
Of all the program code that synchronizes on the same lock, only one thread can be executing it at the same time. That means that if (and only if) all code that interacts with this.o runs synchronized to the this lock, the problems described earlier are avoided.
In your example, the presence of setObjectFromAnyThread() means that you must also synchronize setObjectFromMainThread(), otherwise the state in this.o is accessed sometimes-synchronized and sometimes-unsynchronized, which is a broken program.
Synchronization comes at a cost: because your locking bits of code to be run by one thread at a time (and other threads are made to wait), you remove some or all of the speed-up you gained from using multi-threading in the first place. In some cases, you're better off forgetting multi-threading exists and using a simpler single-threaded program.
Within a multi-threaded program, it's useful to limit the amount of shared, mutable state to a minimum. Any state that's not accessed by more than one thread at a time doesn't need synchronization, and is going to be easier to reason about.
The #MainThread annotation, at least as it exists in Android, indicates that the method is intended to be accessed on the main thread only. It doesn't do anything, it's just there as a signal to both the programmer(s) and the compiler. There is no technical protection mechanism involved at run time; it all comes down to your self-discipline and some compile-time tool support. The advantage of this lack of protection is that there's no runtime overhead.
Multi-threaded programming is complicated and easy to get wrong. The only way to get it right is to truly understand it. There's a book called Java Concurrency In Practice that's a really good explanation of both the general principles and problems of concurrency and the specifics in Java.

Why could this code fail?

While reviewing this question I noticed this code:
class MyThread extends Thread {
private boolean stop = false;
public void run() {
while(!stop) {
doSomeWork();
}
}
public void setStop() {
this.stop = true;
}
}
However I don't understand why would this fail. Do other threads not get access to the "actual" stop variable?
The JIT compiler can re-order reads and writes in an application so long as
the actions are sequentially consistent and
the altered actions do not violate intra-thread semantics.
That is just a fancy way of saying, all actions should appear to happen the same way as if it were executed by only a single thread. So you can get the JIT to recompile your code to look like this
class MyThread extends Thread {
private boolean stop = false;
public void run() {
if(!stop){
while(true){
}
}
}
This is a legal optimization called hoisting. It still acts the same as if serial but offers surprising results when using multiple threads.
By declaring a field volatile you are telling Java not to execute any re orderings. Along with the memory consistency as mentioned by Nathan Hughes
The instance variable stop needs to be volatile, otherwise there's no guarantee the other threads will see changes to it. There are a lot of conflicting interests at work: threads want a consistent view of the program state, CPUs want to be able to cache data, the JVM wants to be able to reorder instructions. Making the instance variable volatile means that it can't be cached and that happens-before relationships are established that limit instruction reordering.
See this other answer (+1) for a good example of what reordering may happen without marking the variable volatile.
(By the way using interruption for thread cancellation is preferable to using an instance variable.)
The variable stop must be declared as volatile.
Although i prefer using interrupt to stop a thread.
Other threads are not guaranteed to see updated values of stop - you need to establish a "happens before" relationship. The simplest way would be to make stop volatile.

Pausing a Thread on Java

given a Runnable:
public class MyRunnable implements Runnable {
public void run() {
doA();
for (i=0; i<18123 ; i++) {
doB();
}
doC();
}
}
where doA,B,C are defined with like 100 lines of code each.
what is the best way to make the thread FREEZE - in whatever line of code its at - and then continue from the next line of code where it last stopped.
I was searching around the net, and I saw here http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
that they suggest on using a boolean, so, does that mean that i need to check that boolean after every few lines of code? there's gotta be a nicer way...
That cannot work in general for the cause Thread.suspend() and Thread.resume() have been deprecated:
Thread.suspend is inherently deadlock-prone. If the target thread holds a lock on the monitor protecting a critical system resource when it is suspended, no thread can access this resource until the target thread is resumed. If the thread that would resume the target thread attempts to lock this monitor prior to calling resume, deadlock results. Such deadlocks typically manifest themselves as "frozen" processes.
If you absolutely need this behavior, you have to explicitly implemented it yourself.
The implementations could look like this (code not tested, nor compiled):
public abstract class SafeStoppableRunnable implements Runnable {
private boolean stopped = false;
public synchronized void stopSafe() {
this.stopped = true;
}
public synchronized void resumeSafe() {
this.stopped = false;
synchronized(this) {
this.notifyAll();
}
}
protected synchronized void waitWhenStopped() {
while(this.stopped) {
this.wait();
}
}
}
The stoppable Runnables should then extend SafeStoppableRunnable and call the method waitWhenStopped() at all the points in your program you want it to be stoppable. Stoppable points are probably points where the program does not hold global ressources other threads need to make progress.
Multithreaded systems are really complex. The golden rule of multithreaded programming is to avoid any code that can potentially raise the level of entropy of the system. Vague system states are impossible to predict and trace.
A thread paused at some unpredictable line is multithreaded programmer's nightmare. At development time it is simply impossible to make sure that the system will be working fine after the thread is woken up at some unknown line. You just can't keep track of all the alternatives. This will 100% result in all kind of weird defects in production.
Adding a couple of definite pause points in a thread is the only way to go.

Possible locking/performance issue

I am working on an application, that processes incoming messages. I am not proficient in java multithreading and I am asking your help, folks. Is there anything wrong with the following app structure.
There is main application class with stopRequested boolean field. And there is internal runnable class that listens for incoming messages and process them. Also there is another thread that sets stopRequested to true.
Is this approach working and reliable, or I am wrong?
Below there is a part of my code:
class ApplicationClass {
// we set this var in another thread
// when it is necessary to stop
private stopRequested = false;
public ApplicationClass() {
// starting message processing thread
(new Thread(new MessageProcessing())).start();
}
private class MessageProcessing implements Runnable {
public void run() {
while (!stopRequested) {
if (getNewMessagesCount() > 0) {
processNewMessages();
}
}
}
}
}
Thank you.
There are a few things to think about.
As sbridges noted stopRequested needs to be volatile to resolve visibility problems (a thread on another core may not see the change otherwise).
If getNewMessagesCount() doesn't block then your while loop will spin and consume the core; this will give you the lowest latency but ties up the entire core.
The code you've listed appears to be a simple processing queue; you're likely going to be better off going with an ArrayBlockingQueue.
It's dangerous to start a new thread from a constructor. The thing to worry about is what happens if getMessageCount() and processNewMessages() are invoked before ApplicationClass is finished being created. Since the instance of ApplicationClass could be in an incomplete state you could find a rather nasty bug. (For the same reason you never want to have your code subscribe as a listener to events from a constructor, by the way.) Check out Effective Java for more background on this topic.
Your while loop should check if the current thread has been interrupted so that it places nice; it should be while (!stopRequested && !Thread.currentThread().isInterrupted())
Writing correct concurrent programs is hard. I highly recommend reading Java Concurrency in Practice; it will save you a lot of pain.
It is hard to comment on performance without knowing more details, you will probably want to benchmark.
The code looks correct, except you will want to make stopRequested volatile. If it is not volatile, the processing thread may not see it being set to false. Rather than use methods like getNewMessageCount(), you might want to use a LinkedBlockingQueue, and use the poll() method on that.

How to abort a thread in a fast and clean way in java?

Here is my problem: I've got a dialog with some parameters that the user can change (via a spinner for example). Each time one of these parameters is changed, I launch a thread to update a 3D view according to the new parameter value.
If the user changes another value (or the same value again by clicking many times on the spinner arrow) while the first thread is working, I would like to abort the first thread (and the update of the 3D view) and launch a new one with the latest parameter value.
How can I do something like that?
PS: There is no loop in the run() method of my thread, so checking for a flag is not an option: the thread updating the 3D view basically only calls a single method that is very long to execute. I can't add any flag in this method asking to abort either as I do not have access to its code.
Try interrupt() as some have said to see if it makes any difference to your thread. If not, try destroying or closing a resource that will make the thread stop. That has a chance of being a little better than trying to throw Thread.stop() at it.
If performance is tolerable, you might view each 3D update as a discrete non-interruptible event and just let it run through to conclusion, checking afterward if there's a new latest update to perform. This might make the GUI a little choppy to users, as they would be able to make five changes, then see the graphical results from how things were five changes ago, then see the result of their latest change. But depending on how long this process is, it might be tolerable, and it would avoid having to kill the thread. Design might look like this:
boolean stopFlag = false;
Object[] latestArgs = null;
public void run() {
while (!stopFlag) {
if (latestArgs != null) {
Object[] args = latestArgs;
latestArgs = null;
perform3dUpdate(args);
} else {
Thread.sleep(500);
}
}
}
public void endThread() {
stopFlag = true;
}
public void updateSettings(Object[] args) {
latestArgs = args;
}
The thread that is updating the 3D view should periodically check some flag (use a volatile boolean) to see if it should terminate. When you want to abort the thread, just set the flag. When the thread next checks the flag, it should simply break out of whatever loop it is using to update the view and return from its run method.
If you truly cannot access the code the Thread is running to have it check a flag, then there is no safe way to stop the Thread. Does this Thread ever terminate normally before your application completes? If so, what causes it to stop?
If it runs for some long period of time, and you simply must end it, you can consider using the deprecated Thread.stop() method. However, it was deprecated for a good reason. If that Thread is stopped while in the middle of some operation that leaves something in an inconsistent state or some resource not cleaned up properly, then you could be in trouble. Here's a note from the documentation:
This method is inherently unsafe.
Stopping a thread with Thread.stop
causes it to unlock all of the
monitors that it has locked (as a
natural consequence of the unchecked
ThreadDeath exception propagating up
the stack). If any of the objects
previously protected by these monitors
were in an inconsistent state, the
damaged objects become visible to
other threads, potentially resulting
in arbitrary behavior. Many uses of
stop should be replaced by code that
simply modifies some variable to
indicate that the target thread should
stop running. The target thread should
check this variable regularly, and
return from its run method in an
orderly fashion if the variable
indicates that it is to stop running.
If the target thread waits for long
periods (on a condition variable, for
example), the interrupt method should
be used to interrupt the wait. For
more information, see Why are
Thread.stop, Thread.suspend and
Thread.resume Deprecated?
Instead of rolling your own boolean flag, why not just use the thread interrupt mechanism already in Java threads? Depending on how the internals were implemented in the code you can't change, you may be able to abort part of its execution too.
Outer Thread:
if(oldThread.isRunning())
{
oldThread.interrupt();
// Be careful if you're doing this in response to a user
// action on the Event Thread
// Blocking the Event Dispatch Thread in Java is BAD BAD BAD
oldThread.join();
}
oldThread = new Thread(someRunnable);
oldThread.start();
Inner Runnable/Thread:
public void run()
{
// If this is all you're doing, interrupts and boolean flags may not work
callExternalMethod(args);
}
public void run()
{
while(!Thread.currentThread().isInterrupted)
{
// If you have multiple steps in here, check interrupted peridically and
// abort the while loop cleanly
}
}
Isn't this a little like asking "How can I abort a thread when no method other than Thread.stop() is available?"
Obviously, the only valid answer is Thread.stop(). Its ugly, could break things in some circumstances, can lead to memory/resource leaks, and is frowned upon by TLEJD (The League of Extraordinary Java Developers), however it can still be useful in a few cases like this. There really isn't any other method if the third party code doesn't have some close method available to it.
OTOH, sometimes there are backdoor close methods. Ie, closing an underlying stream that its working with, or some other resource that it needs to do its job. This is seldom better than just calling Thread.stop() and letting it experience a ThreadDeathException, however.
The accepted answer to this question allows you to submit batch work into a background thread. This might be a better pattern for that:
public abstract class dispatcher<T> extends Thread {
protected abstract void processItem(T work);
private List<T> workItems = new ArrayList<T>();
private boolean stopping = false;
public void submit(T work) {
synchronized(workItems) {
workItems.add(work);
workItems.notify();
}
}
public void exit() {
stopping = true;
synchronized(workItems) {
workItems.notifyAll();
}
this.join();
}
public void run() {
while(!stopping) {
T work;
synchronized(workItems) {
if (workItems.empty()) {
workItems.wait();
continue;
}
work = workItems.remove(0);
}
this.processItem(work);
}
}
}
To use this class, extend it, providing a type for T and an implementation of processItem(). Then just construct one and call start() on it.
You might consider adding an abortPending method:
public void abortPending() {
synchronized(workItems) {
workItems.clear();
}
}
for those cases where the user has skipped ahead of the rendering engine and you want to throw away the work that has been scheduled so far.
A thread will exit once it's run() method is complete, so you need some check which will make it finish the method.
You can interrupt the thread, and then have some check which would periodically check isInterrupted() and return out of the run() method.
You could also use a boolean which gets periodically checked within the thread, and makes it return if so, or put the thread inside a loop if it's doing some repetative task and it will then exit the run() method when you set the boolean. For example,
static boolean shouldExit = false;
Thread t = new Thread(new Runnable() {
public void run() {
while (!shouldExit) {
// do stuff
}
}
}).start();
Unfortunately killing a thread is inherently unsafe due to the possibilities of using resources that can be synchronized by locks and if the thread you kill currently has a lock could result in the program going into deadlock (constant attempt to grab a resource that cannot be obtained). You will have to manually check if it needs to be killed from the thread that you want to stop. Volatile will ensure checking the variable's true value rather than something that may have been stored previously. On a side note Thread.join on the exiting thread to ensure you wait until the dying thread is actually gone before you do anything rather than checking all the time.
You appear to not have any control over the thread that is rendering the screen but you do appear to have control of the spinner component. I would disable the spinner while the thread is rendering the screen. This way the user at least has some feedback relating to their actions.
I suggest that you just prevent multiple Threads by using wait and notify so that if the user changes the value many times it will only run the Thread once. If the users changes the value 10 times it will fire off the Thread at the first change and then any changes made before the Thread is done all get "rolled up" into one notification. That won't stop a Thread but there are no good ways to do that based on your description.
The solutions that purpose the usage of a boolean field are the right direction. But the field must be volatile.
The Java Language Spec says:
"For example, in the following (broken) code fragment, assume that this.done is a non-
volatile boolean field:
while (!this.done)
Thread.sleep(1000);
The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done."
As far as I remember "Java Concurrency in Pratice" purposes to use the interrupt() and interrupted() methods of java.lang.Thread.
The way I have implemented something like this in the past is to implement a shutdown() method in my Runnable subclass which sets an instance variable called should_shutdown to true. The run() method normally does something in a loop, and will periodically check should_shutdown and when it is true, returns, or calls do_shutdown() and then returns.
You should keep a reference to the current worker thread handy, and when the user changes a value, call shutdown() on the current thread, and wait for it to shutdown. Then you can launch a new thread.
I would not recommend using Thread.stop as it was deprecated last time I checked.
Edit:
Read your comment about how your worker thread just calls another method which takes a while to run, so the above does not apply. In this case, your only real options are to try calling interrupt() and see if has any effect. If not, consider somehow manually causing the function your worker thread is calling to break. For example, it sounds like it is doing some complex rendering, so maybe destroy the canvas and cause it to throw an exception. This is not a nice solution, but as far as I can tell, this is the only way to stop a thread in suituations like this.
Since you're dealing with code you don't have access to you're probably out of luck. The standard procedure (as outlined in the other answers) is to have a flag that is checked periodically by the running thread. If the flag is set, do cleanup and exit.
Since that option is not available to you, the only other option is to force quit the running process. This used to be possible by calling Thread.stop(), but that method has been permanently deprecated for the following reason (copied from the javadocs):
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
More info on this topic can be found here.
One absolute sure way you could accomplish your request (although this is not a very efficient way to do this) is to start a new java process via Runtime.exec() and then stopping that process as necessary via Process.destroy(). Sharing state between processes like this is not exactly trivial, however.
Instead of playing with thread starting and stopping, have you considered having the thread observe the properties that you're changing through your interface? You will at some point still want a stop condition for your thread, but this can be done this was as well. If you're a fan of MVC, this fits nicely into that sort of design
Sorry, after re-reading your question, neither this nor any of the other 'check variable' suggestions will solve your problem.
The correct answer is to not use a thread.
You should be using Executors, see the package: java.util.concurrent
Maybe this can help you: How can we kill a running thread in Java?
You can kill a particular thread by setting an external class variable.
Class Outer
{
public static flag=true;
Outer()
{
new Test().start();
}
class Test extends Thread
{
public void run()
{
while(Outer.flag)
{
//do your work here
}
}
}
}
if you want to stop the above thread, set flag variable to false. The other way to kill a thread is just registering it in ThreadGroup, then call destroy(). This way can also be used to kill similar threads by creating them as group or register with group.

Categories

Resources