pvllnspk
pvllnspk

Reputation: 5767

get unexpected values using synchronize

I have a simple snippet of code and try to experiment a little with it, but in the next code I get unclear for me order of output data:

public class Main {

    static int n = 100;

    public static synchronized int decreaseValue(){
        return --n;
    }

    public static void main(String[] args) throws InterruptedException, IOException {


        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread1: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread1");
        t1.start(); 

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    try {
                        System.out.println("Thread2: "+ decreaseValue());
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        },"Thread2");
        t2.start();


        while(true){
            try {
                System.out.println("Main Thread: "+ decreaseValue());
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Can not understand, why I get the such values in the next order:

Thread1: 89 Thread2: 90 Main Thread: 88

PLEASE PAY ATTENTION TO THE N VALUE NOT TO THE ORDER OF CALLING THREADS:

Thread1: 99
Thread2: 98
Main Thread: 97
Main Thread: 95
Thread2: 94
Thread1: 96
Main Thread: 92

Upvotes: 3

Views: 111

Answers (3)

dan
dan

Reputation: 13272

The threads are running concurrently and nothing is imposing the order on wich they should call your decreaseValue() function. You would expect them to be in order since you are doing the same amount of sleep :), but as soon as a thread will start/resume from a sleep, the CPU will place the thread in a running queue (creating an execution order, this is the order that synchronize will guarantee), because of this the order of your printing depends on how the CPU will place the thread in the running queue.

The print on the console is also synchronized (but not in the same block with your decreaseValue), if you are questioning the printing order. The same logic applies to printing as the one to decrease the values.

If you would like to see the prints in the same order that the value was decremented you can move print in the decreaseValue() function. But this will not affect the order in how the values will be decremented.

Upvotes: 1

Marko Topolnik
Marko Topolnik

Reputation: 200168

You must have read somewhere that synchronized must be used to ensure proper ordering, or something similar. The word "ordering" pertains to a different concept from the one you have in mind: it means that there will always be some definite ordering to the execution of synchronized blocks. The ordering is not known in advance, but it will be there every time. Without synchronized, you won't even get that guarantee: one thread could perceive one order, another thread a different order, or not perceive any actions by other threads at all.

About your edit:

If you are concerned about printouts happening out of order, this is because your println statements are outside of synchronized and so can interleave independently of the calls to decreaseValue.

Upvotes: 3

Subhrajyoti Majumder
Subhrajyoti Majumder

Reputation: 41200

Thread runs in parallelly. You can't predict their execution order. You can set thread priority which prioritize its execution order.

Upvotes: 2

Related Questions