簡體   English   中英

Java發生在關系之前

[英]Java happens-before relationship

雖然SO和其他地方有很多關於之前發生過的關系的帖子,但我很難找到對我的問題的確切答案。

考慮兩個Java線程:

最初, flag == falsedata == 0

T1

data = 42;
synchronized(m) {
  flag = true;
}

T2

boolean f;
synchronized(m) {
  f = flag;
}
if (f) {
  int x = data;
}

根據上面的代碼,我相信f可以被賦值為truefalse ,沒有guaruntee。 它是否正確?

現在,如果兩個synchronized語句被更改為synchronized(flag) ,我認為指令flag = true將始終發生在指令f = flag ,因此f將始終被賦值為true 它是否正確?

不,同步不保證首先到達哪個Thread 僅保證多一個Thread不能一次訪問同步塊。

synchronized塊視為門上有鎖的房間。 我們不知道誰會首先到達門口,但一旦他們這樣做,他們就會進門並鎖上門。

其他人必須等到房間里的人准備離開並解鎖門。 一旦發生這種情況,每個人都會再次參加比賽。

這一切都取決於您關閉Thread的順序。 但即便如此,也沒有任何保證,因為JVM可能會隨機地暫停ThreadThreadyield 在類比中 - 領先到門的人可能會在香蕉皮上絆倒。 不太可能,但總是可能的。

如果你想要保證,那么你需要wait / notify - 以便讀取線程檢查flag ,如果它是false ,則在循環中掛起自己。

寫入線程然后設置flag並通知鎖定監視器喚醒讀取線程。

下面是一個使用Java 5中的LockCondition api的示例。我並不是說你必須優先使用它來synchronizedwait / notify - 這只是我躺在我適應的一個例子。

Reader獲取lock ,然后在循環中檢查ready標志。 如果該標志為falseawait該條件。 這會以原子方式釋放lock並掛起Thread

Writer同時獲取lock並設置dataready標志。 然后它調用signalAll並釋放lock

這會喚醒Reader ,然后讀取readytrue並繼續執行print語句。

輸出將始終為42 (從不為-1 )。

public class App {

    static volatile boolean ready = false;
    static volatile int data = -1;

    private static class Reader implements Runnable {

        private final Lock lock;
        private final Condition condition;

        public Reader(Lock lock, Condition condition) {
            this.lock = lock;
            this.condition = condition;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                while (!ready) {
                    try {
                        condition.await();
                    } catch (InterruptedException ex) {
                        //oh well
                    }
                }
                System.out.println(data);
            } finally {
                lock.unlock();
            }
        }
    }

    private static class Writer implements Runnable {

        private final Lock lock;
        private final Condition condition;

        public Writer(Lock lock, Condition condition) {
            this.lock = lock;
            this.condition = condition;
        }

        @Override
        public void run() {
            lock.lock();
            try {
                data = 42;
                ready = true;
                condition.signalAll();
            } finally {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final ExecutorService executorService = Executors.newFixedThreadPool(2);
        final Lock lock = new ReentrantLock();
        final Condition condition = lock.newCondition();
        executorService.execute(new Reader(lock, condition));
        executorService.execute(new Writer(lock, condition));
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.DAYS);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM