2017-07-23 34 views
7

Innymi słowy, chcę wiedzieć, czy zmiana zmiennej przed przerwaniem jest zawsze widoczna, gdy przerwanie zostanie wykryte w przerwanym wątku. Na przykład.Czy wywołanie przerwania() na wątku tworzy się przed relacją z przerwanym wątkiem

private int sharedVariable; 

public static void interruptTest() { 
    Thread someThread = new Thread(() -> { 
     try { 
      Thread.sleep(5000); 
     } catch (InterruptedException e) { 
      // Is it here guaranteed that changes before interrupt are always visible here? 
      System.out.println(sharedVariable); 
     } 
    }); 
    someThread.start(); 
    Thread.sleep(1000); 
    sharedVariable = 10; 
    someThread.interrupt(); 
} 

starałem się znaleźć odpowiedź w Java language specification aw Summary page of the java.util.concurrent package wspomniano w Java tutorial ale interrupt nie zostało wymienione.

Wiem o volatile i innych elementach pierwotnych synchronizacji, ale czy ich potrzebuję?

+0

Nie mogłem znaleźć informacji, z wyjątkiem "Współbieżności Java w praktyce" (patrz Reguła przerwania w http://what-when-how.com/Tutorial/topic-355vueju/Java-Concurrency-in- Practice-417.html). Ale ja jestem biblią, więc najprawdopodobniej jest poprawna. Byłoby miło, gdyby @BrianGoetz potwierdził i wyjaśnił, dlaczego nie znajduje się w javadoc/JLS (chyba, że ​​przeoczyłem to, oczywiście). –

+0

Jeśli miałbym przeformułować pytanie, faktycznie pytasz, czy wywołując Thread.interrupt(), można zagwarantować, że najnowszy stan "sharedVariable" będzie używany z "someThread" bez użycia udokumentowanych sposobów osiągnięcia dzieje-before i współdzielenie stanu (za pomocą blokad, zmiennych atomowych lub zmienności). Odpowiedź na to brzmiałaby nie. Więc tak, myślę, że musiałbyś uczynić go niestabilnym lub użyć blokowania. – jay

+1

@jay - przerwanie _jest_ a [udokumentowane] (https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.4) sposób ustanawiania _happens-before_. – BeeOnRope

Odpowiedz

3

Tak przerywania T2 T1 gwintu z gwintem tworzy stanie, przed związek pomiędzy T1 i T2, jak to opisano w JLS17.4.4. Synchronizacja Zamówienie:

Jeśli gwint T1 przerwań nici T2, przerwanie T1 synchronizacji, w dowolnym momencie, gdy każdy inny wątek (łącznie T2) stwierdzi, że T2 zostały przerwane (poprzez obecność InterruptedException rzucony lub przez wywołanie Thread.interrupted lub Thread.isInterrupted).

Teraz to tylko oznacza, że ​​T1 synchronizuje-z wykrycie przerwania T2, podczas gdy pytasz o dzieje, zanim. Na szczęście ta pierwsza implikuje tę ostatnią z 17.4.5. Zdarza się - przed złożeniem zamówienia:

Dwie akcje można zamówić według relacji zdarza się przed. Jeśli zdarzy się jedna akcja - przed drugą, wtedy pierwsza jest widoczna i przed drugą.

Jeśli mamy dwie akcje xiy, piszemy hb (x, y), aby wskazać, że x ma miejsce - przed y.

  • ...
  • Jeśli akcja x-synchronizuje z następującą czynność y, to mamy też hb (x, y).

więc jesteś bezpieczny dostęp sharedVariable wiedząc, że ma (co najmniej) wartość napisany przez T1, nawet bez volatile.