2011-10-20 10 views

Odpowiedz

8

Użycie metody synchronized powoduje, że metoda/blok staje się dostępny tylko dla wątku naraz. Tak, to jest bezpieczne dla wątków.

Obie koncepcje są połączone, a nie wykluczają się nawzajem. Podczas korzystania z wait() musisz posiadać monitor tego obiektu. Musisz więc wcześniej mieć przed sobą synchronized(..). Użycie wartości .wait() powoduje zatrzymanie bieżącego wątku do momentu, aż inny wątek wywoła .notify() na obiekcie, na którym czeka. Jest to dodatek do synchronized, który gwarantuje, że tylko jeden wątek wejdzie do bloku/metody.

+0

więc dlaczego musimy użyć oczekiwania/powiadamia metodami? muszą być jakieś różnice, prawda? – Alan

+0

see updated .... – Bozho

+1

Myślę, że po zsynchronizowaniu bloku, zwolni on blokadę. Inny wątek, który wykonuje zsynchronizowaną metodę lub instrukcję, blokuje, gdy nie może uzyskać blokady. Działa także jak mechanizm notify() wait, który jest bardzo podobny. Alan pyta, jaka jest różnica posiadania wait() i notify() niż zwykłe zsynchronizowane końce bloków. –

2

Efektywna Java artykuł 69: „Biorąc pod uwagę trudności związane z użyciem poczekać i zawiadomić poprawnie, należy użyć narzędzi współbieżności wyższego poziomu zamiast”.

Unikaj używania wait() i notify(): użyj synchronized, lub innych narzędzi z java.util.concurrent, jeśli to możliwe.

5

więc po tym, jak właśnie zakłopotany w pytaniu wywiadu na tym zdecydowałem się sprawdzić to i zrozumieć to znowu dla miliardowej godziny lol.

zsynchronizowany blok sprawia, że ​​wątek kodu jest bezpieczny. Bez wątpienia. Kiedy wait() i notify() lub notifyAll() wchodzą w to, gdzie próbujesz napisać bardziej efektywny kod. Na przykład, jeśli masz listę elementów, z którymi dzieli się wiele wątków, a następnie umieścisz je w zsynchronizowanym bloku monitora, wątki wątków będą nieustannie przeskakiwać i uruchamiać kod w tył iw przód, w tył i fort podczas przełączania kontekstu ..... .even z pustą listą!

Metoda wait() jest używana na monitorze (obiekt wewnątrz zsynchronizowanego (..)) jako mechanizm służący do powiadamiania wszystkich wątków o wygaśnięciu i zaprzestaniu używania cykli procesora do odwołania lub powiadomieniaAll().

więc coś takiego:

synchronized(monitor) { 

    if(list.isEmpty()) 
     monitor.wait(); 
} 


...somewhere else... 

synchronized(monitor){ 

    list.add(stuff); 
    monitor.notifyAll(); 

} 
+0

Wymagane jest, aby zawsze wywoływać funkcję wait() w pętli, np. while (list.isEmpty()) monitor.wait(), jeśli chcesz poczekać, aż coś zostanie umieszczone na liście przez inny wątek. https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait() – Arthur

+0

To powinna być odpowiedź. Programista nie może wybrać, który zsynchronizowany blok powinien iść pierwszy. Ale wait/notify może wskazać, który blok powinien być pierwszy. +1. –

0

synchroniczny blok jest używany, jeśli 2 nitki „samego obiektu” próbuje accquire blokadę. Ponieważ klasa obiektu trzyma zamek, wie, komu dać. Podczas gdy 2 wątki (np. T2 i t4) z 2 obiektów (t1 & t2 z obj1 i t3 & t4 z obj 2) próbują zdobyć blokadę, obj1 będzie nieświadomy blokady obiektu obj2, a obj2 będzie nieświadomy blokady obiektu obj1 . Dlatego stosowane są metody wait i notify.

np

//example of java synchronized method 
class Table{ 
synchronized void printTable(int n){//synchronized method 
    for(int i=1;i<=5;i++){ 
    System.out.println(n*i); 
    try{ 
     Thread.sleep(400); 
    }catch(Exception e){System.out.println(e);} 
    } 

} 
} 

class MyThread1 extends Thread{ 
Table t; 
MyThread1(Table t){ 
this.t=t; 
} 
public void run(){ 
t.printTable(5); 
} 

} 
class MyThread2 extends Thread{ 
Table t; 
MyThread2(Table t){ 
this.t=t; 
} 
public void run(){ 
t.printTable(100); 
} 
} 

public class TestSynchronization2{ 
public static void main(String args[]){ 
Table obj = new Table();//only one object 
MyThread1 t1=new MyThread1(obj); 
MyThread2 t2=new MyThread2(obj); 
t1.start(); 
t2.start(); 
} 
} 

dwa wątki T1 i T2 należy do tego samego obiektu, stąd synchronizacja działa dobrze tutaj. Natomiast

class Table{ 
synchronized void printTable(int n){//synchronized method 
    for(int i=1;i<=5;i++){ 
    System.out.println(n*i); 
    try{ 
     Thread.sleep(400); 
    }catch(Exception e){System.out.println(e);} 
    } 

} 
} 

class MyThread1 extends Thread{ 
Table t; 
MyThread1(Table t){ 
this.t=t; 
} 
public void run(){ 
t.printTable(5); 
} 

} 
class MyThread2 extends Thread{ 
Table t; 
MyThread2(Table t){ 
this.t=t; 
} 
public void run(){ 
t.printTable(100); 
} 
} 

public class TestSynchronization2{ 
public static void main(String args[]){ 
Table obj = new Table(); 
Table obj1 = new Table(); 
MyThread1 t1=new MyThread1(obj); 
MyThread2 t2=new MyThread2(obj1); 
t1.start(); 
t2.start(); 
} 
} 

Po uruchomieniu powyższego programu, synchronizacja nie działa od każdego wątku należeć do innego obiektu, stąd należy używać oczekiwania i powiadomić tutaj.

0

wait/notify jest wymagany, gdy chcesz poczekać na pewną sytuację (np.dane wejściowe użytkownika) INSIDE zsynchronizowany blok.

Typowe zastosowanie:

synchronized(obj) { 
    // do something 

    while(some condition is not met) { 
     obj.wait(); 
    } 
    // do something other 
} 

Załóżmy, że użytkownik nie korzysta wait(). Następnie musisz zaimplementować zajętą ​​pętlę odpytywania warunku, który chcesz, co jest złe dla wydajności.

synchronized(obj) { 
    // do something 

    while(some condition is not met) { // busy loop } 

    // do something other 
} 

Uwaga: Nawet jeśli wątek jest obudzony przez notify() lub notifyAll() z drugiej gwintem, Awaken wątek robi NIE gwarantowane natychmiast wznowić jego wykonanie. Jeśli istniały inne wątki oczekujące na wykonanie zsynchronizowanego bloku na tym samym obiekcie, to obudzony wątek powinien konkurować z wątkami.

+0

Nie jestem pewien, czy to dobry przykład. wait() jest metodą blokującą, więc nie musi znajdować się w nieskończonej pętli. Możesz po prostu użyć wait() w jednym zsynchronizowanym bloku, a gdy twój warunek zostanie spełniony, możesz użyć funkcji notify() w innym zsynchronizowanym bloku, aby "odblokować" metodę wait(). – Scarfe

1

metoda Making jak synchronized ma dwa skutki:

Po pierwsze, nie jest to możliwe z dwóch zsynchronizowanych wywołań metod na tym samym obiekcie do przeplatania. Kiedy jeden wątek wykonania zsynchronizowany sposób dla obiektu, wszystkie inne nitki, w których wywołuje zsynchronizowane sposoby samym bloku przedmiotu (zawiesić wykonywanie) do pierwszej nici wykonane z obiektem

drugie, gdy zsynchronizowane wyjścia metody , automatycznie ustanawia relację happen-before z każdym kolejnym wywołaniem zsynchronizowanej metody dla tego samego obiektu. Gwarantuje to, że zmiany stanu obiektu są widoczne dla wszystkich wątków.

synchronizacja pomaga chronić kod krytyczny.

Jeśli chcesz nawiązać komunikację między wieloma wątkami, trzeba użyć wait() i notify()/notifyAll()

wait(): Powoduje bieżącego wątku czekać aż inny wątek wywołuje metodę notify() lub metodę notifyAll() dla tego obiektu.

notify(): Budzi pojedynczy wątek oczekujący na monitorze tego obiektu. Jeśli na ten obiekt czekają jakieś wątki, jeden z nich zostaje wybrany do przebudzenia.

: Budzi wszystkie wątki oczekujące na monitorze tego obiektu. Wątek czeka na monitorze obiektu, wywołując jedną z metod oczekiwania.

Prosty futerał do użycia przy użyciu wait() i notify(): Problem producenta i konsumenta.

Wątek konsumenta musi poczekać, aż wątek producenta wygeneruje dane. funkcje wait() i notify() są przydatne w powyższym scenariuszu. W miarę upływu czasu wprowadzono lepsze alternatywy. Zobacz tę samouczek na stronie high level concurrency.

W prostych słowach:

Zastosowanie synchronized na straży ochrony krytycznej sekcję danych i pilnować swój kod.

Użyj wait() i notify() wraz z synchronizacją, jeśli chcesz nawiązać komunikację między wieloma wątkami w bezpieczny sposób, które są wzajemnie od siebie zależne.

Powiązane SE pytania:

What does 'synchronized' mean?

A simple scenario using wait() and notify() in java

Powiązane problemy