Co oznacza „zsynchronizowany”?

993

Mam pytania dotyczące użycia i znaczenia synchronizedsłowa kluczowego.

  • Jakie jest znaczenie synchronizedsłowa kluczowego?
  • Kiedy powinny być metody synchronized?
  • Co to znaczy programowo i logicznie?
Johanna
źródło
1
pomocna dyskusja między hashmap i hashtable oraz synchronizacja: stackoverflow.com/questions/40471/java-hashmap-vs-hashtable
limc
2
Możliwy duplikat Jak działa synchronizacja w Javie
Marian Paździoch
1
Przejrzałem cały link do dokumentacji od pierwszego komentarza i nie zrozumiałem, dopóki nie dotarłem do ostatniego akapitu. Zamiast wklejać linki i nic nie cytować, może być wklejanie linków i dodanie cytatu jest bardziej pomocne.
Rakib

Odpowiedzi:

878

Słowo synchronizedkluczowe dotyczy różnych wątków, które odczytują i zapisują te same zmienne, obiekty i zasoby. To nie jest trywialny temat w Javie, ale oto cytat z Sun:

synchronized metody umożliwiają prostą strategię zapobiegania zakłóceniom wątków i błędom spójności pamięci: jeśli obiekt jest widoczny dla więcej niż jednego wątku, wszystkie odczyty lub zapisy do zmiennych tego obiektu są wykonywane metodami synchronicznymi.

W bardzo, bardzo małym skrócie: kiedy masz dwa wątki, które czytają i zapisują w tym samym „zasobie”, powiedzmy zmienną o nazwie foo, musisz upewnić się, że wątki te uzyskują dostęp do zmiennej w sposób atomowy. Bez synchronizedsłowa kluczowego Twój wątek 1 może nie zobaczyć zmiany wątku 2 dokonanej na foo, lub, co gorsza, może zostać zmieniony tylko w połowie. Nie byłoby to logicznie oczekiwane.

Ponownie jest to nietrywialny temat w Javie. Aby dowiedzieć się więcej, zapoznaj się z tematami tutaj na SO i Interwebs na temat:

Kontynuuj badanie tych tematów, dopóki nazwa „Brian Goetz” nie zostanie trwale powiązana z terminem „współbieżność” w twoim mózgu.

Stu Thompson
źródło
71
Więc w zasadzie to zsynchronizowane słowo kluczowe sprawia, że ​​twoje metody są bezpieczne dla wątków?
Rigo Vides
82
Zsynchronizowane słowo kluczowe jest jednym z narzędzi zapewniających bezpieczeństwo wątku kodu. Samo użycie zsynchronizowanej metody lub zmiennej jako takiej może, ale nie musi, załatwić sprawę. Podstawowa znajomość modelu pamięci Java jest bardzo ważna dla uzyskania poprawnej współbieżności.
Stu Thompson,
28
O ile nie jesteś Brianem Goetzem (a może Jonem Skeetem), prawie niemożliwe jest uzyskanie poprawnej współbieżności Java tylko z podstawowymi językami (synchronizowane, zmienne). Na początek skorzystaj z pakietu java.util.concurrent i zbuduj na nim.
Thilo,
12
Mówiąc dokładniej: zsynchronizowane metody nie mogą być wywoływane w tym samym czasie z wielu wątków.
peterh - Przywróć Monikę
2
@peterh synchronized robi więcej, stąd bardziej szczegółowe wyjaśnienie
Stu Thompson
293

Cóż, myślę, że mieliśmy dość wyjaśnień teoretycznych, więc rozważ ten kod

public class SOP {
    public static void print(String s) {
        System.out.println(s+"\n");
    }
}

public class TestThread extends Thread {
    String name;
    TheDemo theDemo;
    public TestThread(String name,TheDemo theDemo) {
        this.theDemo = theDemo;
        this.name = name;
        start();
    }
    @Override
    public void run() {
        theDemo.test(name);
    }
}

public class TheDemo {
    public synchronized void test(String name) {
        for(int i=0;i<10;i++) {
            SOP.print(name + " :: "+i);
            try{
                Thread.sleep(500);
            } catch (Exception e) {
                SOP.print(e.getMessage());
            }
        }
    }
    public static void main(String[] args) {
        TheDemo theDemo = new TheDemo();
        new TestThread("THREAD 1",theDemo);
        new TestThread("THREAD 2",theDemo);
        new TestThread("THREAD 3",theDemo);
    }
}

Uwaga: synchronizedblokuje wywołanie następnego wątku do metody test (), dopóki wykonanie poprzedniego wątku nie zostanie zakończone. Wątki mogą uzyskiwać dostęp do tej metody pojedynczo. Bez synchronizedwszystkich wątków może uzyskać dostęp do tej metody jednocześnie.

Gdy wątek wywołuje metodę synchroniczną „test” obiektu (tutaj obiekt jest instancją klasy „TheDemo”), uzyskuje blokadę tego obiektu, żaden nowy wątek nie może wywoływać ŻADNEJ metody synchronizacji tego samego obiektu, o ile poprzedni wątek który nabył blokadę, nie zwalnia blokady.

Podobnie dzieje się, gdy wywoływana jest dowolna statyczna zsynchronizowana metoda klasy. Wątek nabywa blokadę związaną z klasą (w tym przypadku dowolna niestatyczna zsynchronizowana metoda wystąpienia tej klasy może zostać wywołana przez dowolny wątek, ponieważ ta blokada poziomu obiektu jest nadal dostępna). Jakikolwiek inny wątek nie będzie mógł wywoływać żadnej statycznej zsynchronizowanej metody klasy, dopóki blokada poziomu klasy nie zostanie zwolniona przez wątek, który obecnie blokuje.

Wyjście zsynchronizowane

THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9

Wyjście bez synchronizacji

THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
Dheeraj Sachan
źródło
7
Świetny przykład, dobrze jest znać teorię, ale kod jest zawsze bardziej szczegółowy i kompletny.
Santi Iglesias
2
@SantiIglesias „Complete”? Nie. Ten przykład pokazuje zachowanie blokujące synchronized, ale spójność pamięci jest ignorowana.
Stu Thompson
2
@Stu Thompson Spójność pamięci jest wynikiem blokowania
Dheeraj Sachan
@DheerajSachan Zgodnie z tą logiką użycie ReentrantLock zapewniłoby spójność pamięci. Tak nie jest.
Stu Thompson,
3
@boltup_im_coding: Metoda start () wprowadza wątek w stan „RUNNABLE”, co oznacza, że ​​jest gotowy do wykonania lub już działa. Może się zdarzyć, że inny wątek (zwykle, ale niekoniecznie o wyższym priorytecie) w stanie Runnable przeskoczy kolejkę i rozpocznie wykonywanie. W powyższym przykładzie THREAD 3 zdarzyło się uzyskać procesor przed THREAD 2.
Sahil J
116

synchronizedKluczowe zapobiega jednoczesnego dostępu do bloku kodu lub obiektu przez wielu wątków. Wszystkie metody Hashtablesynchronized, więc tylko jeden wątek może wykonać dowolną z nich jednocześnie.

Korzystając z innych niż synchronizedkonstrukcje, takich jak HashMap, musisz zbudować funkcje bezpieczeństwa wątków w kodzie, aby zapobiec błędom spójności.

jmort253
źródło
81

synchronizedoznacza, że ​​w środowisku wielowątkowym obiekt mający synchronizedmetodę (metody) / blok (y) nie pozwala dwóm wątkom na dostęp do synchronizedmetody (metod) / bloku (kodów) w tym samym czasie. Oznacza to, że jeden wątek nie może odczytać, a inny wątek go aktualizuje.

Drugi wątek będzie zamiast tego czekać, aż pierwszy wątek zakończy wykonywanie. Narzutem jest szybkość, ale zaletą jest gwarantowana spójność danych.

Jeśli aplikacja jest jednowątkowa, synchronizedbloki nie zapewniają korzyści.

Codemwnci
źródło
54

Słowo synchronizedkluczowe powoduje, że wątek uzyskuje blokadę podczas wprowadzania metody, dzięki czemu tylko jeden wątek może wykonać metodę w tym samym czasie (dla danej instancji obiektu, chyba że jest to metoda statyczna).

Nazywa się to często zabezpieczaniem klasy przed wątkami, ale powiedziałbym, że to eufemizm. Chociaż prawdą jest, że synchronizacja chroni wewnętrzny stan urządzenia Vector przed jego uszkodzeniem, zwykle nie pomaga to użytkownikowi.

Rozważ to:

 if (vector.isEmpty()){
     vector.add(data);
 }

Mimo że zastosowane metody są zsynchronizowane, ponieważ są one blokowane i odblokowywane indywidualnie, dwa niestety czasowe wątki mogą stworzyć wektor z dwoma elementami.

W rezultacie musisz także zsynchronizować kod aplikacji.

Ponieważ synchronizacja na poziomie metody jest a) kosztowna, gdy jej nie potrzebujesz, oraz b) niewystarczająca, gdy potrzebujesz synchronizacji, istnieją teraz niezsynchronizowane zamiany (ArrayList w przypadku Vector).

Niedawno wydany został pakiet współbieżności z wieloma sprytnymi narzędziami, które zajmują się problemami wielowątkowości.

Thilo
źródło
26

Przegląd

Zsynchronizowane słowo kluczowe w Javie ma związek z bezpieczeństwem wątków, to znaczy, gdy wiele wątków odczytuje lub zapisuje tę samą zmienną.
Może się to zdarzyć bezpośrednio (poprzez dostęp do tej samej zmiennej) lub pośrednio (przy użyciu klasy, która korzysta z innej klasy, która uzyskuje dostęp do tej samej zmiennej).

Zsynchronizowane słowo kluczowe służy do zdefiniowania bloku kodu, w którym wiele wątków może uzyskać dostęp do tej samej zmiennej w bezpieczny sposób.

Głębiej

Pod względem składni synchronizedsłowo kluczowe przyjmuje Objectparametr as (zwany obiektem blokady ), po którym następuje { block of code }.

  • Gdy wykonanie napotka to słowo kluczowe, bieżący wątek próbuje „zablokować / nabyć / posiadać” (wybierz) obiekt blokady i wykonać powiązany blok kodu po uzyskaniu blokady.

  • Wszelkie zapisy do zmiennych wewnątrz zsynchronizowanego bloku kodu są gwarantowane, aby były widoczne dla każdego innego wątku, który podobnie wykonuje kod wewnątrz zsynchronizowanego bloku kodu przy użyciu tego samego obiektu blokady .

  • Tylko jeden wątek na raz może przytrzymywać blokadę, w którym to czasie wszystkie inne wątki próbujące uzyskać ten sam obiekt blokady będą czekać (wstrzymają ich wykonanie). Blokada zostanie zwolniona, gdy wykonanie wyjdzie z zsynchronizowanego bloku kodu.

Zsynchronizowane metody:

Dodawanie synchronizedkluczowe z definicją sposobu wynosi dla całego ciała przy czym sposób jest owinięta w sposób zsynchronizowany z bloku kodu obiektowego blokady istoty this (na przykład sposoby) i ClassInQuestion.getClass() (metody Class) .

- Metoda instancji to metoda, która nie ma staticsłowa kluczowego.
- Metoda klasowa to metoda ze staticsłowem kluczowym.

Techniczny

Bez synchronizacji nie ma gwarancji, w jakiej kolejności odczyty i zapisy mają miejsce, prawdopodobnie pozostawiając zmienną z śmieciami.
(Na przykład zmienna może kończyć się połową bitów zapisanych przez jeden wątek i połową bitów zapisanych przez inny wątek, pozostawiając zmienną w stanie, w którym żaden z wątków nie próbował pisać, ale połączony bałagan obu).

Nie wystarczy ukończyć operacji zapisu w wątku przed (czas zegara ściennego), że inny wątek ją odczyta, ponieważ sprzęt mógł buforować wartość zmiennej, a czytający wątek zobaczyłby buforowaną wartość zamiast tego, co zostało zapisane to.

Wniosek

Dlatego w przypadku Javy należy postępować zgodnie z modelem pamięci Java, aby upewnić się, że nie wystąpią błędy wątków.
Innymi słowy: używaj synchronizacji, operacji atomowych lub klas, które wykorzystują je dla Ciebie pod maską.

Źródła

http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Specyfikacja języka Java®, 13.02.2015

Gima
źródło
Przykro mi, ale mam ten przykład i nie rozumiem znaczenia: `Integer i1 = Arrays.asList (1,2,3,4,5) .stream (). FindAny (). Get (); synchronized (i1) {Integer i2 = Arrays.asList (6,7,8,9,10) .parallelStream () .sorted () .findAny (). get (); System.out.println (i1 + „” + i2); } `1. Dlaczego wywołałeś blok przy pierwszej instancji i to wywołanie nie ma wpływu na kod? 2. Druga instancja będzie bezpieczna dla wątków, pomimo pierwszego uruchomienia bloku?
Adryr83
1
@ Adryr83 Jeśli masz pytanie, prawdopodobnie możesz je zadać, zamieszczając nowe pytanie. Ale skoro tu jesteśmy, przeanalizuję, co mogę (twoje pytanie jest trochę trudne do zrozumienia). Z tego, co mogę powiedzieć o tym fragmencie kodu, wydaje się, że nie zawiera on niczego, co wymagałoby synchronizacji. To jest poza kontekstem. Sugestia: Jeśli możesz, spróbuj podzielić kod na mniejsze pojedyncze części, a następnie poszukaj odpowiedzi na ich temat. O wiele łatwiej jest zrozumieć małe i izolowane problemy niż wymyślić jeden duży blok kodu.
Gima
21

Pomyśl o tym jak o kołowrotku, jaki możesz znaleźć na boisku piłkarskim. Są równoległe parki ludzi, którzy chcą się dostać, ale na bramce są „zsynchronizowane”. Tylko jedna osoba na raz może się przedostać. Wszyscy, którzy chcą się przedostać, zrobią to, ale być może będą musieli poczekać, aż przejdą.

Paweł
źródło
16

Co to jest zsynchronizowane słowo kluczowe?

Wątki komunikują się przede wszystkim poprzez współdzielenie dostępu do pól, do których odwołują się pola odniesienia do obiektów. Ta forma komunikacji jest niezwykle wydajna, ale umożliwia dwa rodzaje błędów: błędy interferencji wątków i błędy spójności pamięci . Narzędziem niezbędnym do zapobiegania tym błędom jest synchronizacja.

Zsynchronizowane bloki lub metody zapobiegają interferencji wątków i zapewniają spójność danych. W dowolnym momencie tylko jeden wątek może uzyskać dostęp do zsynchronizowanego bloku lub metody ( sekcja krytyczna ) poprzez uzyskanie blokady. Inne wątki będą czekać na zwolnienie blokady, aby uzyskać dostęp do sekcji krytycznej .

Kiedy metody są synchronizowane?

Metody są synchronizowane po dodaniu synchronizeddo definicji lub deklaracji metody. Możesz także zsynchronizować określony blok kodu za pomocą metody.

Co to znaczy pro gramatycznie i logicznie?

Oznacza to, że tylko jeden wątek może uzyskać dostęp do sekcji krytycznej poprzez uzyskanie blokady. O ile ten wątek nie zwolni tej blokady, wszystkie inne wątki będą musiały poczekać na uzyskanie blokady. Nie mają dostępu do wejścia do sekcji krytycznej bez blokady dostępu .

Nie da się tego zrobić za pomocą magii. Programista odpowiada za identyfikację krytycznych sekcji w aplikacji i odpowiednią ich ochronę. Java zapewnia platformę do ochrony Twojej aplikacji, ale za to, gdzie i za co należy chronić wszystkie sekcje, odpowiedzialny jest programista.

Więcej szczegółów ze strony dokumentacji Java

Wewnętrzne blokady i synchronizacja:

Synchronizacja opiera się na wewnętrznej jednostce zwanej blokadą wewnętrzną lub blokadą monitora. Zamki wewnętrzne odgrywają rolę w obu aspektach synchronizacji: wymuszają wyłączny dostęp do stanu obiektu i ustanawiają relacje, które zdarzają się przed koniecznością widoczności.

Z każdym obiektem jest związana wewnętrzna blokada . Zgodnie z konwencją wątek, który wymaga wyłącznego i spójnego dostępu do pól obiektu, musi uzyskać wewnętrzną blokadę obiektu przed uzyskaniem do nich dostępu, a następnie zwolnić blokadę wewnętrzną, gdy jest to zrobione.

Mówi się, że wątek jest właścicielem wewnętrznego zamka między momentem, w którym zamek uzyskał i zwolnił zamek. Tak długo, jak wątek posiada wewnętrzny zamek, żaden inny wątek nie może uzyskać tego samego zamka. Drugi wątek zostanie zablokowany podczas próby uzyskania blokady.

Gdy wątek zwalnia blokadę wewnętrzną, między tą czynnością a każdym kolejnym nabyciem tej samej blokady ustalana jest relacja „zanim nastąpi”.

Synchronizacja metod ma dwa efekty :

Po pierwsze, niemożliwe jest przeplatanie dwóch wywołań metod zsynchronizowanych dla tego samego obiektu.

Gdy jeden wątek wykonuje zsynchronizowaną metodę dla obiektu, wszystkie inne wątki, które wywołują metody zsynchronizowane dla tego samego bloku obiektu (zawieszają wykonywanie), dopóki pierwszy wątek nie zostanie wykonany z obiektem.

Po drugie, kiedy zsynchronizowana metoda kończy działanie, automatycznie ustanawia relację przed zdarzeniem 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.

Poszukaj innych alternatyw dla synchronizacji w:

Unikać synchronizacji (tej) w Javie?

Ravindra babu
źródło
11

Synchronized normal methododpowiednik Synchronized statement(użyj tego)

class A {
    public synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(this) {
             // all function code
        }
    } 
}

Synchronized static methododpowiednik Synchronized statement(klasa użytkowania)

class A {
    public static synchronized void methodA() {
        // all function code
    }

    equivalent to

    public void methodA() {
        synchronized(A.class) {
             // all function code
        }
    } 
}

Instrukcja zsynchronizowana (przy użyciu zmiennej)

class A {
    private Object lock1 = new Object();

    public void methodA() {
        synchronized(lock1 ) {
             // all function code
        }
    } 
}

Ponieważ synchronizedmamy zarówno Synchronized Methodsi Synchronized Statements. Jednak Synchronized Methodsjest podobny do, Synchronized Statementsdlatego musimy tylko zrozumieć Synchronized Statements.

=> Zasadniczo będziemy mieli

synchronized(object or class) { // object/class use to provides the intrinsic lock
   // code 
}

Oto 2, które pomogą zrozumieć synchronized

  • Z każdym obiektem / klasą jest intrinsic lockpowiązany.
  • Gdy wątek wywołuje a synchronized statement, automatycznie pobiera intrinsic lockdla tego synchronized statement'sobiektu i zwalnia go, gdy metoda powróci. Tak długo, jak wątek jest właścicielem intrinsic lock, ŻADNY inny wątek nie może uzyskać SAMEJ blokady => wątku bezpieczny.

=> Gdy thread Awywołuje synchronized(this){// code 1}=> cały kod bloku (klasa wewnętrzna) gdzie mają synchronized(this)i wszystkie synchronized normal method(klasa wewnętrzna) są zablokowane, ponieważ SAME blokowanie. Uruchomi się po thread Aodblokowaniu („// kod 1” zakończony).

To zachowanie jest podobne do synchronized(a variable){// code 1}lub synchronized(class).

SAME LOCK => blokada (nie zależy od której metody? Lub które instrukcje?)

Używać metody zsynchronizowanej lub instrukcji zsynchronizowanych?

Wolę, synchronized statementsponieważ jest bardziej rozszerzalny. Przykład: w przyszłości wystarczy zsynchronizować tylko część metody. Przykład: masz 2 zsynchronizowane metody i nie mają one ze sobą żadnego związku , jednak gdy wątek uruchomi metodę, zablokuje drugą metodę (może to uniemożliwić użycie synchronized(a variable)).

Jednak zastosowanie metody zsynchronizowanej jest proste, a kod wygląda na prosty. W przypadku niektórych klas istnieje tylko 1 metoda synchroniczna lub wszystkie metody synchronizowane w klasie, które są ze sobą powiązane => możemy użyć, synchronized methodaby kod był krótszy i łatwiejszy do zrozumienia

Uwaga

(nie ma to większego znaczenia synchronized, różni się między przedmiotem i klasą lub nie jest statyczny i statyczny).

  • Podczas korzystania synchronizedlub normalny sposób lub synchronized(this)czy synchronized(non-static variable)będzie zsynchronizowane bazy na każdej instancji obiektu.
  • Podczas korzystania synchronizedlub metoda statyczna lub synchronized(class)czy synchronized(static variable)będzie zsynchronizowane bazę na klasy

Odniesienie

https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

Mam nadzieję, że to pomoże

Phan Van Linh
źródło
11

Oto wyjaśnienie z samouczków Java .

Rozważ następujący kod:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}

if countjest instancją SynchronizedCounter, wówczas synchronizacja tych metod ma dwa efekty:

  • Po pierwsze, niemożliwe jest przeplatanie dwóch wywołań metod zsynchronizowanych dla tego samego obiektu. Gdy jeden wątek wykonuje zsynchronizowaną metodę dla obiektu, wszystkie inne wątki, które wywołują metody zsynchronizowane dla tego samego bloku obiektu (zawieszają wykonywanie), dopóki pierwszy wątek nie zostanie wykonany z obiektem.
  • Po drugie, kiedy zsynchronizowana metoda kończy działanie, automatycznie ustanawia relację przed zdarzeniem 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.
Shahryar Saljoughi
źródło
9

Według mnie synchronizacja oznacza w zasadzie, że kompilator napisał monitor.enter i monitor.exit wokół twojej metody. Jako taki może być bezpieczny dla wątków, w zależności od tego, w jaki sposób jest używany (mam na myśli to, że możesz napisać obiekt za pomocą zsynchronizowanych metod, które nie są bezpieczne dla wątków w zależności od tego, co robi twoja klasa).

Spence
źródło
5

Brak innych odpowiedzi to jeden ważny aspekt: bariery pamięci . Synchronizacja wątków zasadniczo składa się z dwóch części: serializacji i widoczności. Radzę wszystkim, aby szukali w Google „bariery pamięci jvm”, ponieważ jest to nietrywialny i niezwykle ważny temat (jeśli zmodyfikujesz udostępnione dane, do których dostęp ma wiele wątków). Po zrobieniu tego radzę przyjrzeć się klasom pakietu java.util.concurrent, które pomagają uniknąć jawnej synchronizacji, co z kolei pomaga utrzymać proste i wydajne programy, a nawet zapobiegać impasom.

Jednym z takich przykładów jest ConcurrentLinkedDeque . W połączeniu z wzorcem poleceń pozwala tworzyć wysoce wydajne wątki robocze poprzez upychanie poleceń do współbieżnej kolejki - nie jest wymagana jawna synchronizacja, nie jest możliwe zakleszczenie, nie jest konieczne jawne sleep (), wystarczy sondować kolejkę, wywołując take ().

W skrócie: „synchronizacja pamięci” zachodzi niejawnie, gdy zaczynasz wątek, wątek kończy się, czytasz zmienną zmienną, odblokowujesz monitor (zostawiasz zsynchronizowany blok / funkcję) itp. Ta „synchronizacja” wpływa (w pewnym sensie) „spłukuje” „) wszystkie zapisy wykonane przed tym konkretnym działaniem. W przypadku wspomnianego ConcurrentLinkedDeque dokumentacja „mówi”:

Efekty spójności pamięci: Podobnie jak w przypadku innych współbieżnych kolekcji, akcje w wątku przed umieszczeniem obiektu w ConcurrentLinkedDeque mają miejsce przed czynnościami po dostępie lub usunięciu tego elementu z ConcurrentLinkedDeque w innym wątku.

To niejawne zachowanie jest dość zgubnym aspektem, ponieważ większość programistów Java bez większego doświadczenia po prostu bierze tyle, ile podano. A potem nagle potykają się o ten wątek, gdy Java nie robi tego, co „powinno” robić w środowisku produkcyjnym, w którym występuje inne obciążenie pracą - i dość trudno jest przetestować problemy z współbieżnością.

użytkownik1050755
źródło
3

Zsynchronizowany oznacza po prostu, że wiele wątków, jeśli jest skojarzonych z jednym obiektem, może zapobiec niepoprawnemu odczytowi i zapisowi, jeśli na danym obiekcie używany jest blok synchroniczny. Aby dać ci większą jasność, weźmy przykład:

class MyRunnable implements Runnable {
    int var = 10;
    @Override
    public void run() {
        call();
    }

    public void call() {
        synchronized (this) {
            for (int i = 0; i < 4; i++) {
                var++;
                System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
            }
        }
    }
}

public class MutlipleThreadsRunnable {
    public static void main(String[] args) {
        MyRunnable runnable1 = new MyRunnable();
        MyRunnable runnable2 = new MyRunnable();
        Thread t1 = new Thread(runnable1);
        t1.setName("Thread -1");
        Thread t2 = new Thread(runnable2);
        t2.setName("Thread -2");
        Thread t3 = new Thread(runnable1);
        t3.setName("Thread -3");
        t1.start();
        t2.start();
        t3.start();
    }
}

Stworzyliśmy dwa obiekty klasy MyRunnable, runnable1 jest współdzielony z wątkiem 1, a wątek 3 i runnable2 są współdzielone tylko z wątkiem 2. Teraz, gdy t1 i t3 zaczynają się bez synchronizacji, dane wyjściowe PFB sugerują, że oba wątki 1 i 3 wpływają jednocześnie na wartość var, gdzie dla wątku 2 var ma swoją pamięć.

Without Synchronized keyword

    Current Thread Thread -1 var value 11
    Current Thread Thread -2 var value 11
    Current Thread Thread -2 var value 12
    Current Thread Thread -2 var value 13
    Current Thread Thread -2 var value 14
    Current Thread Thread -1 var value 12
    Current Thread Thread -3 var value 13
    Current Thread Thread -3 var value 15
    Current Thread Thread -1 var value 14
    Current Thread Thread -1 var value 17
    Current Thread Thread -3 var value 16
    Current Thread Thread -3 var value 18

Przy użyciu synchronizacji wątek 3 czeka na zakończenie wątku 1 we wszystkich scenariuszach. Uzyskano dwie blokady, jedną w runnable1 współdzieloną przez wątek 1 i wątek 3, a drugą w runnable2 współdzieloną tylko przez wątek 2.

Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
paras4all
źródło
Zsynchronizowany oznacza jeszcze więcej: ma ogromny wpływ na barierę pamięci.
user1050755
1

zsynchronizowana prosta oznacza, że ​​żadne dwa wątki nie mogą jednocześnie uzyskać dostępu do bloku / metody. Kiedy mówimy, że dowolny blok / metoda klasy jest zsynchronizowana, oznacza to, że tylko jeden wątek może uzyskać do nich dostęp jednocześnie. Wątek, który próbuje uzyskać do niego dostęp, najpierw blokuje ten obiekt i dopóki ta blokada nie jest dostępna, żaden inny wątek nie może uzyskać dostępu do żadnej zsynchronizowanych metod / bloków tej instancji klasy.

Uwaga: inny wątek może uzyskać dostęp do metody tego samego obiektu, który nie jest zdefiniowany jako synchronizowany. Wątek może zwolnić blokadę przez wywołanie

Object.wait()
Aniket Thakur
źródło
0

synchronizedblok w Javie to monitor wielowątkowy. synchronizedblok z tym samym obiektem / klasą może być wykonany tylko przez jeden wątek, wszystkie inne czekają. Może to pomóc w race conditionsytuacji, gdy kilka wątków próbuje zaktualizować tę samą zmienną (pierwszy krok to użycie volatileO mnie )

Java 5rozszerzone synchronizedpoprzez wsparcie [O firmie happens-before]

Odblokowanie (zsynchronizowane wyjście bloku lub metody) monitora następuje przed każdym kolejnym zablokowaniem (zsynchronizowanym blokiem lub wejściem metody) tego samego monitora.

Następnym krokiem jest java.util.concurrent

lotny vs zsynchronizowany

yoAlex5
źródło
-6

Synchronized to słowo kluczowe w Javie, które służy do tego, aby zdarzyło się przed relacją w środowisku wielowątkowym, aby uniknąć niespójności pamięci i błędu interferencji wątku.

Sharad
źródło