Search code examples
javaconcurrencysignalsvolatileshutdown

Java: Shutdown without a volatile variable?


Following scenario:

I have a application, which runs for weeks and then i want to shut it down gracefully.

The following code do the trick:

Main-Thread:

boolean volatile active=true;

while(active)
{
    //loop-code (very fast)
}


//shutdown-thread, called once after a few weeks

active=false;

So now after each loop-iteration, i have a look up in the main memory, cause of that volatile read (right?!).

And i dont want that, only for that shutdown after a few weeks.

Are there any other solution, that my main-thread get notified about that shutdown?

Any signal that goes directly into the main-thread-cache? so that it dont have to look-up itself in the main memory each time, but get notified from extern?

Or any other solution?

Edit (integrate my own answer into this question):

a possible solution could be, reducing the volatile access, see the following code:

boolean volatile active=true;


while(active)
{
    for(int i=0; i<100; ++i)
    {
        //loop-code
    }
}

so with that solution i can reduce the volatile reads, but i increase, after a shutdown the max loop-iterations from 1 to 100.

that solution decrease the volatile access, but dont eliminate it fully.


Solution

  • Your assumption that a volatile read always hits main memory doesn't hold for cache-coherent systems. The volatile read should hit L1 until the other thread modifies the flag and invalidates the cacheline upon which the variable resides.

    However, volatile reads establish a happens-before relation with subsequent accesses, so this prevents the compiler and CPU from performing certain latency-hiding tricks. Instead, use opaque access mode to lessen the impact (thanks Holger :)).

    Something like this should be fast, though I'll leave the benchmarking up to you:

    AtomicBoolean active = new AtomicBoolean(true);
    
    while(active.getOpaque())
    {
        //loop-code (very fast)
    }
    
    
    //shutdown-thread, called once after a few weeks
    
    active.setOpaque(false);
    

    If you're wondering what all these access modes are, here's a nice summary: Using JDK 9 Memory Order Modes.