two threads sometimes observe the same variable value and sometimes not

48 views Asked by At

on my windows machine the following code stops, but if I check less entries in the array (say 100, but you can try less to be on the safe side) the code never ends. Could you explain that?

What the code basically does is demonstrating how thread t2 is not aware of the assignment to the array by t1 (could be fixed by using @Volatile)

    public static void main(String[] args) throws InterruptedException {
        int[] arr = new int[200];
        for (int i=0; i<arr.length; i++) {
            arr[i] = 0;
        }
        Thread t1 = new Thread(() -> {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            for (int i=0; i<arr.length; i++) {
                arr[i] = 1;
            }
        });
        Thread t2 = new Thread(() -> {
            while (true) {
                if (arr[0] == 1
                        || arr[1] == 1
                        || arr[2] == 1
                        || arr[3] == 1
                        || arr[4] == 1
                        || arr[5] == 1
                        || arr[6] == 1
                        || arr[7] == 1
                        || arr[8] == 1
                        || arr[9] == 1
                        || arr[10] == 1
                        || arr[11] == 1
                        || arr[12] == 1
                        || arr[13] == 1
                        || arr[14] == 1
                        || arr[15] == 1
                        || arr[16] == 1
                        || arr[17] == 1
                        || arr[18] == 1
                        || arr[19] == 1
                        || arr[20] == 1
                        || arr[21] == 1
                        || arr[22] == 1
                        || arr[23] == 1
                        || arr[24] == 1
                        || arr[25] == 1
                        || arr[26] == 1
                        || arr[27] == 1
                        || arr[28] == 1
                        || arr[29] == 1
                        || arr[30] == 1
                        || arr[31] == 1
                        || arr[32] == 1
                        || arr[33] == 1
                        || arr[34] == 1
                        || arr[35] == 1
                        || arr[36] == 1
                        || arr[37] == 1
                        || arr[38] == 1
                        || arr[39] == 1
                        || arr[40] == 1
                        || arr[41] == 1
                        || arr[42] == 1
                        || arr[43] == 1
                        || arr[44] == 1
                        || arr[45] == 1
                        || arr[46] == 1
                        || arr[47] == 1
                        || arr[48] == 1
                        || arr[49] == 1
                        || arr[50] == 1
                        || arr[51] == 1
                        || arr[52] == 1
                        || arr[53] == 1
                        || arr[54] == 1
                        || arr[55] == 1
                        || arr[56] == 1
                        || arr[57] == 1
                        || arr[58] == 1
                        || arr[59] == 1
                        || arr[60] == 1
                        || arr[61] == 1
                        || arr[62] == 1
                        || arr[63] == 1
                        || arr[64] == 1
                        || arr[65] == 1
                        || arr[66] == 1
                        || arr[67] == 1
                        || arr[68] == 1
                        || arr[69] == 1
                        || arr[70] == 1
                        || arr[71] == 1
                        || arr[72] == 1
                        || arr[73] == 1
                        || arr[74] == 1
                        || arr[75] == 1
                        || arr[76] == 1
                        || arr[77] == 1
                        || arr[78] == 1
                        || arr[79] == 1
                        || arr[80] == 1
                        || arr[81] == 1
                        || arr[82] == 1
                        || arr[83] == 1
                        || arr[84] == 1
                        || arr[85] == 1
                        || arr[86] == 1
                        || arr[87] == 1
                        || arr[88] == 1
                        || arr[89] == 1
                        || arr[90] == 1
                        || arr[91] == 1
                        || arr[92] == 1
                        || arr[93] == 1
                        || arr[94] == 1
                        || arr[95] == 1
                        || arr[96] == 1
                        || arr[97] == 1
                        || arr[98] == 1
                        || arr[99] == 1
                        || arr[100] == 1
                        || arr[101] == 1
                        || arr[102] == 1
                        || arr[103] == 1
                        || arr[104] == 1
                        || arr[105] == 1
                        || arr[106] == 1
                        || arr[107] == 1
                        || arr[108] == 1
                        || arr[109] == 1
                        || arr[110] == 1
                        || arr[111] == 1
                        || arr[112] == 1
                        || arr[113] == 1
                        || arr[114] == 1
                        || arr[115] == 1
                        || arr[116] == 1
                        || arr[117] == 1
                        || arr[118] == 1
                        || arr[119] == 1
                        || arr[120] == 1
                        || arr[121] == 1
                        || arr[122] == 1
                        || arr[123] == 1
                        || arr[124] == 1
                        || arr[125] == 1
                        || arr[126] == 1
                        || arr[127] == 1
                        || arr[128] == 1
                        || arr[129] == 1
                        || arr[130] == 1
                        || arr[131] == 1
                        || arr[132] == 1
                        || arr[133] == 1
                        || arr[134] == 1
                        || arr[135] == 1
                        || arr[136] == 1
                        || arr[137] == 1
                        || arr[138] == 1
                        || arr[139] == 1
                        || arr[140] == 1
                        || arr[141] == 1
                        || arr[142] == 1
                        || arr[143] == 1
                        || arr[144] == 1
                        || arr[145] == 1
                        || arr[146] == 1
                        || arr[147] == 1
                        || arr[148] == 1
                        || arr[149] == 1
                        || arr[150] == 1
                        || arr[151] == 1
                        || arr[152] == 1
                        || arr[153] == 1
                        || arr[154] == 1
                        || arr[155] == 1
                        || arr[156] == 1
                        || arr[157] == 1
                        || arr[158] == 1
                        || arr[159] == 1
                        || arr[160] == 1
                        || arr[161] == 1
                        || arr[162] == 1
                        || arr[163] == 1
                        || arr[164] == 1
                        || arr[165] == 1
                        || arr[166] == 1
                        || arr[167] == 1
                        || arr[168] == 1
                        || arr[169] == 1
                        || arr[170] == 1
                        || arr[171] == 1
                        || arr[172] == 1
                        || arr[173] == 1
                        || arr[174] == 1
                        || arr[175] == 1
                        || arr[176] == 1
                        || arr[177] == 1
                        || arr[178] == 1
                        || arr[179] == 1
                        || arr[180] == 1
                        || arr[181] == 1
                        || arr[182] == 1
                        || arr[183] == 1
                        || arr[184] == 1
                        || arr[185] == 1
                        || arr[186] == 1
                        || arr[187] == 1
                        || arr[188] == 1
                        || arr[189] == 1
                        || arr[190] == 1
                        || arr[191] == 1
                        || arr[192] == 1
                        || arr[193] == 1
                        || arr[194] == 1
                        || arr[195] == 1
                        || arr[196] == 1
                        || arr[197] == 1
                        || arr[198] == 1
                        || arr[199] == 1
                ) {
                    break;
                }
            }
        });
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println("finished");
    }
1

There are 1 answers

1
Basil Bourque On

final

Mark your arr as final to ensure its reference is never reassigned to another array. And, importantly, final guarantees visibility across threads. No need then for volatile.

final int[] arr = new int[200];

Array writes may not be visible across threads

Writing to the contents of an array is not thread-safe. Assignments made to any slot of the array may or may not be seen by another thread.

AtomicIntegerArray

The simplest solution is to replace your array with AtomicIntegerArray.

final AtomicIntegerArray atomicArr = new AtomicIntegerArray( 200 );

Looping atomic array is not atomic

Be aware of yet another thread-safety issue. As your code accesses each element of the AtomicIntegerArray, another thread could be making changes to the atomic array. When you start checking the first element of the array for our target value 1, the array could contain elements with a 1. But by the time you get to check that element with a 1, that element might have been reassigned a different value other than 1.

Your Question is not clear on whether changes to the array while looping is a problem for you or not.


By the way, replace your lengthy code:

if (arr[0] == 1
                        || arr[1] == 1
                        || arr[2] == 1
…

… with a loop:

boolean found1 = false
for (int index = 0 ; index < length ; index ++) {
    if ( arr( index ] == 1 ) {
        found1 = true ;
        break ;
    }
}

Using the atomic structure:

boolean found1 = false
for (int index = 0 ; index < atomicArr.length(); index ++) {
    if ( atomicArr.get( index ) == 1 ) {
        found1 = true ;
        break ;
    }
}