简体   繁体   中英

Main thread stops in an infinite loop

I have a small program presenting the user with a GUI to select a file, the program then executes based on the files contents and presents the results accordingly.

This is the loop running in the main thread (the main() method):

do {
    args = fg.getFile();
} while (!fg.started);

fg.started is a boolean variable set to true when the user has selected a file and presses the "start" button.

However, this does not work UNLESS I put a random task inside the loop:

do {
    args = fg.getFile();
    System.out.println("");
} while (!fg.started);

This works.

Can anyone explain to me why this is?

I'm aware of a solution involving the Thread class, with notify() and wait() etc, but now I'm just curious about this.

You should syncronize the access of fg otherwise this may happen:

  • Thread1 could possibly become active, access and therefor block fg , and then get paused.
  • Thread2 becomes active, can't access fg and get's deactivated immediately.
  • Thread1 is active again, finishes the task an may instantaniously reaccess fg , then pause.
  • Thread2 becomse active and ... damn! fg is locked again!

If you need help/instructions on concurrency/parallel execution, see Oracle - Syncronization for information.

fg.started is a boolean variable set to true when the user has selected a file and presses the "start" button.

However, this does not work UNLESS I put a random task inside the loop:

That's because two threads are accessing the started field without memory synchronization. You don't show the definition of fg.started but I suspect that you need to make sure that it is volatile . You also might consider switching to an AtomicBoolean . Here's the Java tutorial about memory synchronization .

volatile boolean started;

The issue with multi-threaded applications is that parts of your program can run in different processors with their own local memory cache. Whenever threads modify or access shared fields there needs to be explicit synchronization to ensure that they aren't just looking at the local cached value of the field.

It is working when you add a System.out.println(...) because the PrintStream 's methods are synchronized so you are adding indirect memory synchronization.

making getFile() synchronized fixed it, thanks. Care to explain why? :)

Because, like the System.out.println(...) you are adding indirect synchronization.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM