0

I expected to output be 0 0 1 1 2 2 ... but the output was 0 1 2 3 ... 0 1 2 3

class Runner: Thread() {
    override fun run() {
        var i = 0
        while (i < 10) {
            println("${Thread.currentThread().name} $i")
            i++
        }

        try {
            Thread.sleep(100)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

fun main(args: Array<String>) {
    val nah = Runner()
    val blah = Runner()

    nah.start()
    blah.start()
}

What is incorrect?

  • okay. Thread sleep should be in the while clause. But why? –  Jul 22 '17 at 04:12
  • Thread creation in actual system takes some time. – Naetmul Jul 22 '17 at 05:10
  • 1
    I think I have already mentioned in your previous question. you must to unserstand what is "**happens-before**" [here](https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.5) & [here](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility) and [here](https://www.google.com.hk/#newwindow=1&safe=strict&q=site:https://docs.oracle.com/javase/tutorial+happens-before) in thread first. in this case you also can using `CyclicBarrier(2)` to fetch the expected result. there is no need such a `Thread.sleep` in your case. – holi-java Jul 22 '17 at 14:45

2 Answers2

2

Well, the output of this code can basically be any interleaved version of the two threads' numbers. They'll both individually print the numbers from 1 to 10 in sequence, but there is no guarantee for when this happens in relation to each other, since there's no synchronization between them, and without the delay inside the loop, they are both just trying to print the numbers as fast possible.

These are all perfectly valid outcomes for this code:

T1    1   2   3
T2      1   2   3
out   1 1 2 2 3 3

T1    1 2 3
T2          1 2 3
out   1 2 3 1 2 3

T1          1 2 3
T2    1 2 3
out   1 2 3 1 2 3

T1    1   2 3
T2      1     2 3
out   1 1 2 3 2 3

If you put the delay inside the loop, and it's long enough, you'll somewhat guarantee that you get a sequence like 1 1 2 2 3 3, but the order in which the two copies of a number are printed between the threads is still up to how the threads happen to get scheduled in a particular run.

      < ~100 ms >
T1   1           2           3
T2    1           2           3
out  11          22          33

T1    1           2           3
T2   1           2           3
out  11          22          33

T1    1          2            3
T2   1            2          3
out  11          22          33

Note that Thread.sleep itself isn't perfectly accurate either, and using it for this purpose will just happen to work out most of the time if you put in a long enough delay here.

If you want to write multithreaded code that runs predictably, look into different synchronization methods (synchronized, locks, semaphores, etc).

zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • With @Synchronized annotation the output is 0 0 1 1 2 3 2 ... is this correct too? –  Jul 22 '17 at 17:54
  • Kotlin's `@Synchronized` annotation is the same as having the `synchronized` keyword there in Java. This only prevents different threads entering a method of an object at the same time. This does nothing in this case, as your two threads are two different object instances. See [here](https://stackoverflow.com/questions/6214229/question-about-java-synchronized). – zsmb13 Jul 22 '17 at 18:58
0

Change to

class Runner: Thread() {
    override fun run() {
        var i = 0
        while (i < 10) {
            println("${Thread.currentThread().name} $i")
            i++
            try {
                Thread.sleep(100)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

Maybe it's close to you, but this result is not always there.

T1 1
T2 1
T1 2
T2 2
T1 3
T2 3
. . .

Ahmad Aghazadeh
  • 16,571
  • 12
  • 101
  • 98