How can you ensure in java that a block of code can not be interrupted by any other thread
Asked Answered
D

11

13

exampl:

new Thread(new Runnable() {
  public void run() {
    while(condition) {

      *code that must not be interrupted*

      *some more code*
    }
  }
}).start();

SomeOtherThread.start();

YetAntherThread.start();

How can you ensure that code that must not be interrupted won't be interrupted?

Desalvo answered 3/12, 2008 at 17:2 Comment(6)
You better be damn sure that code terminates, or you're in big trouble.Fieldstone
Interrupted how? Access to a conflicted resource? The only thread allowed to run at that point in time?Smart
It depends what you mean by "interrupted"... Do you mean: (a) you don't want the thread to catch an InterruptedException, (b) you don't want the thread swapped out by the JVM scheduler, or (c) you don't want the java process swapped out by the underling OS (e.g., you want to clear hw interrupts)?Fieldstone
Thanks all for the replies. I meant indeed not interruptable by other threads in the java process this thread is in. I'm trying to implement some rpg game mechanics in an applet.Desalvo
define interruptable!!! do you mean you want to prevent other threads from calling the interrupt method on this thread?? You're being vagueLilialiliaceous
I am looking for an answer to a related question - #54561257Spokeshave
A
14

You can't - at least not with normal Java, running on a normal, non-real-time operating system. Even if other threads don't interrupt yours, other processes might well do so. Basically you won't be able to guarantee that you get a CPU all to yourself until you're done. If you want this sort of guarantee you should use something like Java Real-Time System. I don't know enough about it to know whether that would definitely provide the facility you want though.

The best thing to do is avoid that requirement in the first place.

Adamite answered 3/12, 2008 at 17:17 Comment(2)
Good comment!. Do you know how this works for a multiprocessor machines? I'm aware of single CPU, but I don't know if there's a way to dedicate let's say 1 CPU to a single process.Weatherworn
It really depends on the operating system. I believe Windows has a bitmask to say which processors a process is willing to run on, but I'm not sure whether you can specify "and don't run anything else on that core!"Adamite
F
4

Assuming you're only concerned with application-level thread contention, and assuming you are willing to fuss with locks as suggested by others (which, IMHO, is a really bad idea), then you should use a ReadWriteLock and not simple object synchronization:

import java.java.util.concurrent.locks.*;

// create a fair read/write lock
final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);

// the main thread grabs the write lock to exclude other threads
final Lock writeLock = rwLock.writeLock();

// All other threads hold the read lock whenever they do 
// *anything* to make sure the writer is exclusive when 
// it is running. NOTE: the other threads must also 
// occasionally *drop* the lock so the writer has a chance 
// to run!
final Lock readLock = rwLock.readLock();

new Thread(new Runnable() {
  public void run() {
    while(condition) {

      writeLock.lock();
      try {
        *code that must not be interrupted*
      } finally {
        writeLock.unlock();
      }

      *some more code*
    }
  }
}).start();

new SomeOtherThread(readLock).start();
new YetAntherThread(readLock).start();
Fieldstone answered 3/12, 2008 at 17:32 Comment(6)
can you explain what is wrong with a simple synchronized block?Haldane
This solution fails to address the many threads started by the runtime itself. Making un-interruptible code, even at the JVM-level, requires realtime support.Discussant
@litb If all threads synchronize on the same lock, then no two threads can ever run concurrently. With a ReadWriteLock, the readers can execute concurrently, but the writer gets to run alone.Fieldstone
@Discussant I agree. This is a better solution (to a sort of a fake problem) than some offered, but not a good solution.Fieldstone
chris, wasn't that exactly what we wanted to tell him? i.e that only one threads gets into the critical section and no other thread concurrently? in your code, you have exactly the same stuff like if you did it with synchronized, as far as i can tell.Haldane
@litb If the main thread is not in the critical sections, then how many other threads are runnable? Look at the docs for ReadWriteLock.Fieldstone
W
3

Actually, you can do this if you control the thread instance you are running on. Obviously, there are a ton of caveats on this (like hanging io operations), but essentially you can subclass Thread and override the interrupt() method. you can then put some sort of boolean in place such that when you flip a flag, interrupt() calls on your thread are either ignored or better yet stored for later.

Welt answered 3/12, 2008 at 17:34 Comment(2)
Normal Thread scheduling in Java is something entirely different from interrupting a Thread. This approach isn't going to do it.Humoral
I'm reading the question as being about Thread.interrupt(), not thread scheduling. At least that's the situation I'm in now. If that's what was meant, then would this be a good answer?Maclay
L
3

You really need to leave more info.

You cannot stop other system processes from executing unless you run on a real-time OS. Is that what you mean?

You cannot stop garbage collection, etc unless you run a real-time java. Is that what you wanted?

The only thing left is: If you simply want all YOUR other java threads to not interrupt each other because they all tend to access some resource willy-nilly without control, you are doing it wrong. Design it correctly so that objects/data that NEED to be accessed in a synchronized manner are synchronized then don't worry about other threads interrupting you because your synchronized objects are safe.

Did I miss any possible cases?

Lightheaded answered 3/12, 2008 at 18:11 Comment(4)
Yes you did. Assuming that somebody is doing it wrong just because you can't think of cases in which this would be desirable is not being constructive.Desalvo
I suppose the other case is that you didn't ask the right question. If your question was "How can I make this section of code perform as well as possible", then you shouldn't be asking about interrupts, you should be looking into thread priorities.Lightheaded
Would you agree that if I had displayed more knowledge of java implemantation details you would have anwsered differently? Or not at all maybe?Desalvo
No, I honestly can't see any other reason to do what you are asking. You still haven't clarified. Is it for performance, or safety (Both of which I addressed) or is there some third possibility you are keeping secret? You said there was a third possibility, but didn't elaborate, I'm quite curiousLightheaded
W
3

Using the synchronized approach ( in the various forms posted here ) doesn't help at all.

That approach only helps to make sure that one thread executes the critical section at a time, but this is not what you want. You need to to prevent the thread from being interrupted.

The read/write lock seems to help, but makes no difference since no other thread is attempting to use the write lock.

It only makes the application a little slower because the JVM has to perform extra validations to execute the synchronized section ( used only by one thread , thus a waste of CPU )

Actually in the way you have it, the thread is not "really" being interrupted. But it seems like it does, because it has to yield CPU time to other threads. The way threads works is; the CPU gives to each thread a chance to run for a little while for very shorts periods of time. Even one when a single thread running, that thread is yielding CPU time with other threads of other applications ( Assuming a single processor machine to keep the discussion simple ).

That's probably the reason it seems to you like the thread is being paused/interrupted from time to time, because the system is letting each thread in the app run for a little while.

So, what can you do?

To increase the perception of no interruptions, one thing you can do is assign a higher priority to your thread and decrease it for the rest.

If all the threads have the same priority one possible schedule of threads 1,2,3 could be like this:

evenly distributed

1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3

While setting max for 1, and min for 2,3 it could be like this:

More cpu to thread 1

1,1,1,2,1,1,3,1,1,1,2,1,1,1,3,1,2,1,1,1

For a thread to be interrupted by another thread, it has to be in an interruptable state, achieved by calling, Object.wait, Thread.join, or Thread.sleep

Below some amusing code to experiment.


Code 1: Test how to change the priority of the threads. See the patterns on the ouput.

public class Test {
    public static void main( String [] args ) throws InterruptedException {
        Thread one = new Thread(){
            public void run(){
                while ( true ) {
                    System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
                }
            }
        };
        Thread two = new Thread(){
            public void run(){
                while ( true ) {
                    System.out.println(".............................................");
                }
            }
        };
        Thread three = new Thread(){
            public void run(){
                while ( true ) {
                    System.out.println("------------------------------------------");
                }
            }
        };

        // Try uncommenting this one by one and see the difference.

        //one.setPriority( Thread.MAX_PRIORITY );
        //two.setPriority( Thread.MIN_PRIORITY );
        //three.setPriority( Thread.MIN_PRIORITY );
        one.start();
        two.start();
        three.start();

        // The code below makes no difference
        // because "one" is not interruptable
        Thread.sleep( 10000 ); // This is the "main" thread, letting the others thread run for aprox 10 secs.
        one.interrupt();  // Nice try though.
    }
}

Code 2. Sample of how can be a thread actually be interrupted ( while sleeping in this case )

public class X{
    public static void main( String [] args ) throws InterruptedException  {
        Thread a = new Thread(){ 

            public void run(){ 

                int i = 1 ; 
                while ( true ){ 
                    if ( i++ % 100 == 0 ) try {
                        System.out.println("Sleeping...");
                        Thread.sleep(500);
                    } catch ( InterruptedException ie ) {
                        System.out.println( "I was interrpted from my sleep. We all shall die!! " );
                        System.exit(0);
                    }
                    System.out.print("E,"); 
                }
            }

         };
        a.start();


        Thread.sleep( 3000 ); // Main thread letting run "a" for 3 secs. 
        a.interrupt(); // It will succeed only if the thread is in an interruptable state
    }
}
Weatherworn answered 3/12, 2008 at 21:9 Comment(0)
D
2

Before a thread is interrupted, security manager's checkAccess() method is called. Implement your own security manager, call System.setSecurityManager to install it and make sure it doesn't let any other thread interrupt you while it is in critical section.

Diphyodont answered 3/12, 2008 at 18:14 Comment(1)
This sounds interesting. You actually ever did this?Desalvo
G
2

Error processing is an example of a use case where it is very useful to stop threads from being interrupted. Say you have a large multi-threaded server and some external condition arises that causes errors to be detected on multiple worker threads simultaneously. Each worker thread generates a notification that an error occurred. Let's say further the desired response is to bring the server to a safe state that will allow it to restart after the error condition is cleared.

One way to implement this behavior is to have a state machine for the server that processes state changes in total order. Once an error notification arrives, you put it into the state machine and let the state machine process it in toto without interruption. This is where you want to avoid interruptions--you want the first notification to cause the error handler to run. Further notifications should not interrupt or restart it. This sounds easy but really isn't--suppose the state machine was putting the server online. You would want to interrupt that to let error processing run instead. So some things are interruptible but others are not.

If you interrupt the error processing thread it may blow the error handler out of the water during synchronized method processing, leaving objects in a potentially dirty state. This is the crux of the problem--thread interrupts go around the normal synchronization mechanism in Java.

This situation is rare in normal applications. However, when it does arise the result can be byzantine failures that are very difficult to anticipate let alone cure. The answer is to protect such critical sections from interrupts.

Java does not as far as I can tell give you a mechanism to stop a thread from being interrupted. Even if it did, you probably would not want to use it because the interrupt could easily occur in low-level libraries (e.g., TCP/IP socket processing) where the effect of turning off interrupts can be very unpredictable.

Instead, it seems as if the best way to handle this is to design your application in such a way that such interrupts do not occur. I am the author of a small state machine package called Tungsten FSM (https://code.google.com/p/tungsten-fsm). FSM implements a simple finite-state machine that ensures events are processed in total order. I'm currently working on a bug fix that addresses exactly the problem described here. FSM will offer one way to address this problem but there are many others. I suspect most of them involve some sort of state machine and/or event queue.

If you take the approach of preventing interruptions it of course creates another problem if non-interruptible threads become blocked for some reason. At that point you are simply stuck and have to restart the process. It does not seem all that different from a deadlock between Java threads, which is in fact one way non-interruptible threads can become blocked. There's really no free lunch on these types of issues in Java.

I have spent a lot of time looking at problems like this--they are very difficult to diagnose let alone solve. Java does not really handle this kind of concurrency problem very well at all. It would be great to hear about better approaches.

Gaynellegayner answered 4/5, 2013 at 16:56 Comment(0)
P
1

Just start your own sub-thread, and make sure that the interrupt calls never filter through to it.

new Thread(new Runnable() {
  public void run() {
    Thread t = new Thread() {
      public void run() {
        *code that must not be interrupted*
      }
    }
    t.start(); //Nothing else holds a reference to t, so nothing call call interrupt() on it, except for your own code inside t, or malicious code that gets a list of every live thread and interrupts it.

      while( t.isAlive() ) {
        try {
          t.join();
        } catch( InterruptedException e ) {
          //Nope, I'm busy.
        }
      }

      *some more code*
    }
  }
}).start();

SomeOtherThread.start();

YetAntherThread.start();
Prestonprestress answered 11/1, 2014 at 21:44 Comment(1)
this thread could probably still get interrupted, if you don't control all the code in itNonstandard
W
1

I think you need to lock on an interrupt flag. What about something like this (not tested):

new Thread() {
    boolean[] allowInterrupts = { true };

    @Override
    public void run() {
        while(condition) {
            allowInterrupts[0] = false;
            *code that must not be interrupted*
            allowInterrupts[0] = true;
            *some more code*
        }
    }

    @Override
    public void interrupt() {
        synchronized (allowInterrupts) {
            if (allowInterrupts[0]) {
                super.interrupt();
            }
        }
    }
}.start();

SomeOtherThread.start();

YetAntherThread.start();
Whorton answered 6/10, 2014 at 22:51 Comment(0)
N
0

Best halfway solution would be to synchronize all threads on some common object so that no other threads are runnable while you're in the critical section.

Other than that I do not think it's possible. And I'm quite curious as to what kind of problem that requires this type of solution ?

Narcotize answered 3/12, 2008 at 17:9 Comment(3)
Synchronizing on 1 single object would make all thread uninterruptible everywhere. You need a ReadWriteLock.Fieldstone
yeah but if you don't control all threads - for example Garbage Collection or what notNonstandard
The reason I am looking for this feature is to prevent Zalgo, which can happen in asynchronous coding patterns. You need some code further down a block to register before a callback does, etc. So you need to make sure the code further down the block executes in some deterministic amount of time, etc.Nonstandard
A
-1

A usual program does not randomly interrupt threads. So if you start a new Thread and you are not passing the reference to this Thread around, you can be quite sure that nothing will interrupt that Thread.

Keep the reference to the Thread private is sufficient in most scenarios. Everything else would be hacky.

Typically work queues like ExecutorService will interrupt their Thread's when asked to do so. In these cases you want to deal with interrupts.

Andyane answered 5/11, 2018 at 20:17 Comment(1)
@MrCholo have a look at this article: ibm.com/developerworks/library/j-jtp05236/index.html - it shows some examples and scenariosAndyane

© 2022 - 2024 — McMap. All rights reserved.