Could the JIT collapse two volatile reads as one in certain expressions?

后端 未结 5 680
礼貌的吻别
礼貌的吻别 2021-01-31 04:11

Suppose we have a volatile int a. One thread does

while (true) {
    a = 1;
    a = 0;
}

and another thread does

w         


        
5条回答
  •  死守一世寂寞
    2021-01-31 04:15

    As laid out in other answers there are two reads and two writes. Imagine the following execution (T1 and T2 denote two threads), using annotations that match the JLS statement below:

    • T1: a = 0 //W(r)
    • T2: read temp1 = a //r_initial
    • T1: a = 1 //w
    • T2: read temp2 = a //r
    • T2: print temp1+temp2

    In a concurrrent environment this is definitely a possible thread interleaving. Your question is then: would the JVM be allowed to make r observe W(r) and read 0 instead of 1?

    JLS #17.4.5 states:

    A set of actions A is happens-before consistent if for all reads r in A, where W(r) is the write action seen by r, it is not the case that either hb(r, W(r)) or that there exists a write w in A such that w.v = r.v and hb(W(r), w) and hb(w, r).

    The optimisation you propose (temp = a; print (2 * temp);) would violate that requirement. So your optimisation can only work if there is no intervening write between r_initial and r, which can't be guaranteed in a typical multi threaded framework.

    As a side comment, note however that there is no guarantee as to how long it will take for the writes to become visible from the reading thread. See for example: Detailed semantics of volatile regarding timeliness of visibility.

提交回复
热议问题