Gro
Gro

Reputation: 31

Java threads counter "issue"?

I was trying impact of thread priority and when println in run method stays in comment both threads end in the same time and I don't understand this behavior, can you explain ? Thank you.

Main.class

public class Main {

public static void main(String[] args) {
    Test t1 = new Test("Thread #1");
    Test t2 = new Test("Thread #2");

    t1.thread.setPriority(10);
    t2.thread.setPriority(1);

    t1.thread.start();
    t2.thread.start();

    try {
        t1.thread.join();
        t2.thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    System.out.println(t1.thread.getName() + ": " + t1.count);
    System.out.println(t2.thread.getName() + ": " + t2.count);

    System.out.println("End of main thread.");
}

}   

Test.class

public class Test implements Runnable{ 
    public Thread thread;
    static boolean stop = false;
    int count = 0;

    public Test(String name){
        thread = new Thread(this, name);
    }

    @Override
    public void run(){

        for(int i = 0; i < 10000000 && stop == false; i++){
            count = i;
            //System.out.println(count + " " + thread.getName());
        }
        stop = true;

        System.out.println("End of " + thread.getName());
    }
}

     without println          with println

    End of Thread #1        End of Thread #1
    End of Thread #2        End of Thread #2
    Thread #1: 9999999      Thread #1: 9999999
    Thread #2: 9999999      Thread #2: 3265646
    End of main thread.     End of main thread.

Upvotes: 2

Views: 126

Answers (2)

Mike Robinson
Mike Robinson

Reputation: 8965

To clarify: the only purpose of thread/process "priority," in any language environment on any operating system, is to suggest to the OS "which of these two 'ought to be, I think, run first'," if both of them happen to be instantaneously "runnable" and a choice must be made to run only one of them.

(In my experience, the best example of this in-practice is the Unix/Linux nice command, which voluntarily reduces the execution-priority of a command by a noticeable amount.) CPU-intensive workloads which perform little I/O can actually benefit from being given a reduced priority.

As other answerers have already stressed, it is impossible to predict "what will actually happen," and priority can never be used to alter this premise. You must explicitly use appropriate synchronization-primitives to assure that your code executes properly in all situations.

Upvotes: 3

Holger
Holger

Reputation: 298389

Your two threads access a shared mutable variable without proper synchronization. In this case, there is no guaranty about when (or whether at all) a thread will learn about a change made by another thread. In your case, the change made by one thread is not noticed by the other at all. Note that while for a primitive data type like boolean, not reading the up to date value is the worst thing that can happen, for non-primitive data types, even worse problems, i.e. inconsistent results could occur.

Inserting a print statement has the side effect of synchronizing the threads, because the PrintStream perform an internal synchronization. Since there is no guaranty that System.out will contain such a synchronizing print stream implementation, this is an implementation specific side-effect.

If you change the declaration of stop to

static volatile boolean stop = false;

the threads will re-read the value from the shared heap in each iteration, reacting immediately on the change, at the cost of reduced overall performance.

Note that there are still no guarantees that this code works as you expect, as there is no guaranty about neither, that the thread priority has any effect nor that threads run in parallel at all. Thread scheduling is implementation and environment dependent behavior. E.g. you might find out that not the thread with the highest priority finishes its loop first, but just the thread that happened to be started first.

Upvotes: 4

Related Questions