-1

I'm currently developing an app that in some test cases, goes on a infinite loop, but if I redo the same tests, it goes on well. To prevent it, I'm using a secondary thread to monitor the time passed since the start of a task, but I'm currently not using synchronized blocks, because I don't know how to.

Here is an example:

public class ThreadHarvest {
    private static final ReentrantLock lock = new ReentrantLock();
    private static boolean safe;

    public static void main(String[] args) throws InterruptedException
    {
        Thread task = new Thread(() ->{
            lock.lock();
            safe = false;

            for (long i = 10000000L; i > 0L; --i)
                System.out.println(i);

            safe = true;
            lock.unlock();

            System.out.println("Safe ended!");
        });

        task.start();

        while (lock.isLocked() == false);

        lock.tryLock(5, TimeUnit.SECONDS);

        if (!safe)
        {
            task.stop();
            System.out.println("Force ended!");
        }
    }
}

Also, there is a specific area that is guaranteed to be safe, which is just after the lock is released. And I know too that the stop method is deprecated, so if you happen to have some good ideas to make it less error prone, I'd be very thankful :D

Gray
  • 115,027
  • 24
  • 293
  • 354
João Esteves
  • 89
  • 1
  • 1
  • 3
  • Note: As `boolean safe` is not volatile, your main thread might not see that change. – Peter Lawrey Feb 06 '16 at 00:15
  • 2
    Synchronization isn't a defence against infinite loops, but it is a possible way to convert them into deadlocks. Your question doesn't make sense. – user207421 May 25 '16 at 01:57
  • @PeterLawrey iirc, `ReentrantLock` also make sure the change being visible. (you may Google for `java reentrantlock memory barrier`). The way OP using it *seems* working fine (need more inspection though :P ) – Adrian Shum May 25 '16 at 01:59
  • OP: afaik, there is no proper way in Java to "force" ending a thread. You may want to search for how to deal with similar situation by Googling `Java thread interrupt`. In brief, your thread should be rewritten to prepare for interruption, and your main thread interrupt corresponding thread to try to stop them from continue working. – Adrian Shum May 25 '16 at 02:04

1 Answers1

0

I don't really understand your question but here are some general comments about your code.

  • You should never have a spin loop like that. I'd add a Thread.sleep(10); or something.
  • With locks, you should always put your unlock in a lock; try { } finally { unlock; }. Then you know your lock will be unlocked even if it throws an exception.
  • If you are accessing a field in two different threads you must protect it somehow. You could use an AtomicBoolean for safe or mark it as a volatile boolean otherwise the main thread might not see any changes to it. There are no guarantees of memory synchronization with isLocked() or tryLock().
  • Instead of your lock and safe, how about just trying to do a task.join(5, TimeUnit.SECONDS) and then test if (task.isAlive()) { killItWithFire(); }.

I'm currently developing an app that in some test cases, goes on a infinite loop,

Seems to me like you should be be concentrating your time fixing this problem. The thread.stop() is a real hack.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • 1
    one opinion: it should be `lock; try {...} finally {unlock;}` instead. You don't want to unlock if there is anything wrong happen in lock – Adrian Shum May 25 '16 at 01:52
  • 1
    Another thing is, I doubt if using `AtomicBoolean` or `volatile` is needed here. `ReentrantLock` is also serving the purpose for memory barrier (just like `synchronized`) – Adrian Shum May 25 '16 at 01:54
  • Good point wrt the lock @AdrianShum. Fixed. Safe can be set to true _before_ the !safe test which may be ok but I'd rather be safe, especially since the `tryLock(...)` makes no guarantee about memory synchronization according to the docs unless it's successful. – Gray May 25 '16 at 02:41
  • @Gary oh you are right. I originally thought the last part of `!safe` checking happens after successful tryLock – Adrian Shum May 25 '16 at 02:51