Domanda

Ho alcune domande riguardanti l'uso e il significato di synchronized parola chiave.

  • Qual è il significato di synchronized parola chiave?
  • Quando dovrebbero essere i metodi synchronized?
  • Cosa significa a livello di programmazione e logica?
È stato utile?

Soluzione

La parola chiave synchronized è tutto su diversi thread leggere e scrivere le stesse variabili, oggetti e risorse. Questo non è un argomento banale in Java, ma qui è una citazione da sole:

  

Metodi synchronized consentono una semplice   strategia per prevenire filo   coerenza interferenza e memoria   errori: se un oggetto è visibile a   più di un thread, tutte le letture o   scrive a variabili che sono oggetto di   fatto attraverso metodi sincronizzati.

In un molto, molto piccolo poche parole: Quando si dispone di due thread in lettura e scrittura per lo stesso 'risorsa', dire una foo variabile denominata, è necessario assicurarsi che questi fili accedono al variabile in modo atomico. Senza la parola chiave synchronized, il thread 1 non può vedere il cambiamento filo 2 fatto per foo, o peggio, può essere modificato solo la metà. Questo non sarebbe quello che logicamente aspettate.

Ancora una volta, questo è un argomento non banale in Java. Per saperne di più, esplorare argomenti qui su SO e le Interwebs circa:

Tenere esplorare questi temi fino a quando il nome di "Brian Goetz" diventa permanentemente associato con il termine "concorrenza" nel vostro cervello.

Altri suggerimenti

Bene, penso che ne abbiamo abbastanza di spiegazioni teoriche, quindi considera questo codice

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);
    }
}

Nota: synchronized blocca la chiamata del thread successivo al metodo test() finché l'esecuzione del thread precedente non è terminata.I thread possono accedere a questo metodo uno alla volta.Senza synchronized tutti i thread possono accedere a questo metodo contemporaneamente.

Quando un thread chiama il metodo sincronizzato 'test' dell'oggetto (qui l'oggetto è un'istanza della classe 'TheDemo') acquisisce il blocco di quell'oggetto, qualsiasi nuovo thread non può chiamare NESSUN metodo sincronizzato dello stesso oggetto finché il thread precedente che aveva acquisito il blocco non rilascia il blocco.

Una cosa simile accade quando viene chiamato un metodo sincronizzato statico della classe.Il thread acquisisce il lock associato alla classe (in questo caso qualsiasi metodo sincronizzato non statico di un'istanza di quella classe può essere chiamato da qualsiasi thread perché quel lock a livello di oggetto è ancora disponibile).Qualsiasi altro thread non sarà in grado di chiamare alcun metodo statico sincronizzato della classe finché il blocco a livello di classe non viene rilasciato dal thread che attualmente detiene il blocco.

Uscita con sincronizzato

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

Uscita senza sincronizzata

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

La parola synchronized impedisce l'accesso simultaneo a un blocco di codice o oggetto da più thread. Per default, un Hashtable è synchronized, in modo che solo un thread può accedere alla tabella alla volta.

Su utilizzo di non-synchronized costruisce come HashMap, è necessario costruire le caratteristiche di sicurezza filo nel codice per evitare errori di coerenza di memoria.

synchronized significa che in un ambiente multi filettato, un metodo oggetto avente synchronized (s) / blocco (s) non lascia due fili per accedere al metodo synchronized (s) / blocco (s) del codice allo stesso tempo. Ciò significa che un thread non può leggere mentre un altro thread lo aggiorna.

Il secondo filo sarà invece attendere finché il primo thread completa la sua esecuzione. L'overhead è la velocità, ma il vantaggio è garantita la coerenza dei dati.

Se l'applicazione è a thread singolo, però, i blocchi synchronized non fornisce benefici.

La parola chiave synchronized provoca un filo per ottenere un blocco entrando nel metodo, in modo che solo un thread può eseguire il metodo contemporaneamente (per l'determinata istanza di oggetto, a meno che sia un metodo statico).

Questo è spesso chiamato rendendo la classe thread-safe, ma direi che questo è un eufemismo. Se è vero che la sincronizzazione protegge lo stato interno del vettore da venire corrotto, questo di solito non aiuta l'utente del vettore molto.

Considerate questo:

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

Anche se i metodi coinvolti sono sincronizzati, perché vengono bloccati e sbloccati singolarmente, due fili purtroppo temporizzati possono creare un vettore a due elementi.

Quindi, in effetti, è necessario sincronizzare nel codice dell'applicazione pure.

Poiché la sincronizzazione a livello di metodo è un) costoso quando non serve e b) insufficiente quando si ha bisogno di sincronizzazione, ora ci sono le sostituzioni non-sincronizzata (ArrayList nel caso del vettore).

In tempi più recenti, il pacchetto concorrenza è stato rilasciato, con una serie di utility intelligenti che si occupano di questioni di multi-threading.

Panoramica

parola chiave sincronizzato in Java ha a che fare con il filo di sicurezza, cioè quando più thread leggere o scrivere la stessa variabile.
questo può avvenire direttamente (accedendo alla stessa variabile) o indirettamente (tramite una classe che utilizza un'altra classe che accede alla stessa variabile).

La parola sincronizzata viene utilizzata per definire un blocco di codice in cui più thread possono accedere alla stessa variabile in modo sicuro.

Deeper

Syntax-saggio la parola synchronized prende un Object come è il parametro (chiamato un oggetto di blocco ), che viene poi seguita da una { block of code }.

  • Quando l'esecuzione rileva questa parola chiave, il thread corrente cerca di "blocco / acquisire / proprio" (sceglierne) oggetto di blocco ed eseguire il blocco associato di codice dopo che lock stato acquisito.

  • Qualsiasi scritture variabili all'interno del blocco di codice sincronizzato sono garantiti per essere visibile a tutti gli altri thread che esegue analogamente codice all'interno di un blocco di codice sincronizzato utilizzando la stessa oggetto di blocco .

  • solo thread alla volta può tenere il blocco, durante il quale tutti gli altri thread cercano di acquisire la stessa oggetto di blocco attenderà (sospendere l'esecuzione). Il blocco viene rilasciato quando l'esecuzione esce dal blocco di codice sincronizzato.

metodi sincronizzati:

Aggiunta synchronized parola chiave per una definizione di metodo è uguale al corpo intero procedimento essendo avvolto in un blocco di codice sincronizzato con il oggetto di blocco essere this (per metodi di istanza) e ClassInQuestion.getClass() (per i metodi di classe) .

- metodo di istanza è un metodo che non ha static parola chiave
. - metodo di classe è un metodo che ha static parola chiave

.

Tecnico

Senza sincronizzazione, non è garantito in quale ordine la lettura e scrittura accadere, possibilmente lasciando la variabile di immondizia.
(ad esempio una variabile potrebbe finire con la metà dei bit scritti da un filo e la metà dei bit scritti da un altro thread, lasciando la variabile in uno stato che nessuno dei fili cercato di scrivere, ma un disastro combinato di entrambe.)

Non è sufficiente per completare un'operazione di scrittura in un thread prima (tempo di orologio a muro) un altro thread lo legge, in quanto l'hardware potrebbe essere memorizzata nella cache il valore della variabile, e il filo di lettura vedrebbe il valore memorizzato nella cache invece di quello che è stato scritto ad esso.

Conclusione

In questo modo, nel caso di Java, è necessario seguire il modello di memoria Java per garantire che gli errori di threading non accadono.
In altre parole:. Utilizzare la sincronizzazione, operazioni atomiche o le classi che li utilizzano per voi sotto le cappe

  

Fonti

     

http://docs.oracle.com/javase/specs/jls/se8 /html/index.html
   Java® Language Specification, 2015/2/13

Pensate a come una sorta di tornello come si potrebbe trovare in un campo di calcio. Ci sono vapori parallele di persone che vogliono entrare ma al tornello sono 'sincronizzate'. Solo una persona alla volta può ottenere attraverso. Tutti coloro che vogliono ottenere attraverso la farà, ma potrebbe essere necessario aspettare fino a che non possono passare attraverso.

  

Qual è la parola sincronizzato?

Le discussioni comunicano principalmente attraverso la condivisione di accesso ai campi e gli oggetti di riferimento si riferiscono a campi. Questa forma di comunicazione è estremamente efficiente, ma fa due tipi di errori possibili: errori interferenze filo e la memoria di coerenza . L'utensile necessario per evitare questi errori è la sincronizzazione.

blocchi o metodi sincronizzati impedisce interferenze filo e assicurarsi che i dati siano coerenti. In qualsiasi punto di tempo, solo un thread può accedere a un blocco o metodo ( sezione critica ) sincronizzato con l'acquisizione di una serratura. Altro thread (s) attenderà per il rilascio di blocco per l'accesso sezione critica .

  

Quando sono metodi sincronizzati?

I metodi sono sincronizzati quando si aggiunge synchronized a definizione di metodo o di dichiarazione. È anche possibile sincronizzare un particolare blocco di codice con-in un metodo.

  

Che cosa significa pro grammaticalmente e logicamente?

Ciò significa che solo un thread può accedere sezione critica acquisendo una serratura. A meno che questa discussione rilascio questo blocco, tutti gli altri fili (s) dovrà aspettare di acquisire un blocco. Essi non hanno accesso per entrare in sezione critica con fuori blocco acquisizione.

Questo non può essere fatto con una magia. E 'programmatore responsabilità di individuare sezione critica (s) in applicazione e la guardia di conseguenza. Java fornisce un quadro per proteggere la vostra applicazione, ma dove e cosa tutte le sezioni ad essere custodito è responsabilità del programmatore.

Maggiori dettagli da documentazione java pagina

intrinseci Serrature e Sincronizzazione:

  

Sincronizzazione è costruito attorno ad un'entità interna nota come la serratura intrinseca o blocco del monitor. serrature intrinseche giocano un ruolo in entrambi gli aspetti della sincronizzazione:. rispettare accesso esclusivo a stato e stabilire di un oggetto che accade-prima di relazioni che sono essenziali per la visibilità

Ogni oggetto ha un blocco intrinseca ad esso associati . Per convenzione, un filo che deve accedere esclusivo e coerente ai campi di un oggetto deve acquisire serratura intrinseca dell'oggetto prima di accedere, e quindi rilasciare il blocco intrinseca quando è fatto con loro.

Un filo si dice che possiede blocco intrinseco tra il tempo che ha acquisito la serratura e rilasciato il blocco. Finché un filo possiede una serratura intrinseco, nessun altro thread può acquisire la stessa serratura. L'altro filo bloccherà quando tenta di acquisire il blocco.

  

Quando un thread rilascia un blocco intrinseco, un accade-prima che venga stabilita rapporto tra tale azione e ogni successiva acquisizione della stessa serratura.

Fare metodi sincronizzati ha due effetti :

  

In primo luogo, non è possibile che due invocazioni di metodi sincronizzati sullo stesso oggetto per interlacciare.

Quando un thread sta eseguendo un metodo sincronizzato per un oggetto, tutti gli altri thread che richiamano i metodi per lo stesso blocco oggetto (sospendere l'esecuzione) sincronizzati fino al primo filo avviene con l'oggetto.

  

In secondo luogo, quando un sincronizzate esce metodo, si stabilisce automaticamente accade-prima relazione con ogni successiva invocazione di un metodo sincronizzato per lo stesso oggetto.

Ciò garantisce che modifica lo stato dell'oggetto sono visibili tutti i filetti.

cercare altre alternative per la sincronizzazione in:

Evitare sincronizzato (questo) in Java?

Ecco una spiegazione da Java Tutorial .

Si consideri il seguente codice:

public class SynchronizedCounter {
    private int c = 0;

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

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

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

se count è un'istanza di SynchronizedCounter, quindi rendendo questi metodi sincronizzati ha due effetti:

     
      
  • In primo luogo, non è possibile che due invocazioni di metodi sincronizzati sullo stesso oggetto per interlacciare. Quando un thread sta eseguendo un metodo sincronizzato per un oggetto, tutti gli altri thread che richiamano i metodi per lo stesso blocco oggetto (sospendere l'esecuzione) sincronizzati fino al primo filo avviene con l'oggetto.
  •   
  • In secondo luogo, quando un sincronizzate esce metodo, si stabilisce automaticamente accade-prima relazione con ogni successiva invocazione di un metodo sincronizzato per lo stesso oggetto. Ciò garantisce che modifica lo stato dell'oggetto sono visibili tutti i filetti.
  •   

Synchronized normal method equivalente aSynchronized statement (Usa questo)

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

    equivalent to

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

Synchronized static method equivalente a Synchronized statement (usa la classe)

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

    equivalent to

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

Istruzione sincronizzata (utilizzando la variabile)

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

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

Per synchronized, abbiamo entrambi Synchronized Methods E Synchronized Statements.Tuttavia, Synchronized Methods è simile a Synchronized Statements quindi dobbiamo solo capire Synchronized Statements.

=> Fondamentalmente, avremo

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

Ecco 2 pensieri che aiutano a capire synchronized

  • Ogni oggetto/classe ha un intrinsic lock ad esso associato.
  • Quando un thread invoca a synchronized statement, acquisisce automaticamente il file intrinsic lock per quello synchronized statement's oggetto e lo rilascia quando il metodo ritorna.Finché un thread possiede un file intrinsic lock, Nessun altro il thread può acquisire il file STESSO blocca => thread-safe.

=> Quando un thread A invoca synchronized(this){// code 1} => tutto il codice del blocco (all'interno della classe) dove have synchronized(this) e tutto synchronized normal method (all'interno della classe) è bloccato perché STESSO serratura.Verrà eseguito dopo thread A sbloccare ("// codice 1" terminato).

Questo comportamento è simile a synchronized(a variable){// code 1} O synchronized(class).

STESSA SERRATURA => blocca (non dipende da quale metodo?o quali affermazioni?)

Utilizzare il metodo sincronizzato o le istruzioni sincronizzate?

preferisco synchronized statements perché è più estensibile.Ad esempio, in futuro sarà necessario sincronizzare solo una parte del metodo.Ad esempio, hai 2 metodi sincronizzati e it non ne ho rilevanti l'uno per l'altro, tuttavia quando un thread esegue un metodo, bloccherà l'altro metodo (può impedire utilizzando use synchronized(a variable)).

Tuttavia, applicare il metodo sincronizzato è semplice e il codice sembra semplice.Per alcune classi, esiste solo 1 metodo sincronizzato o tutti i metodi sincronizzati nella classe sono rilevanti tra loro => possiamo usare synchronized method per rendere il codice più breve e facile da capire

Nota

(non è rilevante per molto synchronized, è la differenza tra oggetto e classe o non statico e statico).

  • Quando usi synchronized o metodo normale o synchronized(this) O synchronized(non-static variable) verrà sincronizzato in base a ciascuna istanza dell'oggetto.
  • Quando usi synchronized o metodo statico o synchronized(class) O synchronized(static variable) verrà sincronizzato in base alla classe

Riferimento

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

Spero che sia d'aiuto

Per la mia comprensione sincronizzato in pratica significa che il compilatore scrivere la Monitor.Enter e Monitor.Exit intorno al vostro metodo. Come tale può essere thread-safe a seconda di come viene utilizzato (quello che voglio dire è che si può scrivere un oggetto con metodi sincronizzati che non è threadsafe seconda di ciò che la classe fa).

Quali altre risposte sono mancanti è un aspetto importante: barriere di memoria . sincronizzazione dei thread è costituito essenzialmente da due parti: la serializzazione e la visibilità. Io consiglio a tutti di google per "barriera di memoria JVM", in quanto è un argomento non banale ed estremamente importanti (se si modificano i dati condivisi a cui si accede da più thread). Dopo averlo fatto, vi consiglio di guardare le classi del pacchetto java.util.concurrent che aiutano a evitare di utilizzare la sincronizzazione esplicita, che a sua volta aiuta a mantenere i programmi di semplice ed efficiente, forse anche prevenire situazioni di stallo.

Un esempio è ConcurrentLinkedDeque . Insieme con la modello di comando permette di creare thread di lavoro altamente efficienti da ripieno comandi nella coda concomitante -. nessuna sincronizzazione esplicita necessario, senza deadlock possibile, non dormire esplicito () necessaria, proprio sondaggio la coda chiamando take ()

In breve: "Sincronizzazione memoria" accade implicitamente quando si avvia un filo, un'estremità del filo, si legge un variabile volatile, si sblocca un monitor (lasciare un blocco / funzione sincronizzato) ecc "sincronizzazione" influenza (in un certo senso "vampate") tutti di scritture effettuate prima di quella particolare azione. Nel caso del suddetto ConcurrentLinkedDeque , la documentazione "dice":

  

Effetti consistenza di memoria: Come con altre collezioni contemporanee,   azioni in un filo prima di collocare un oggetto in un   ConcurrentLinkedDeque accadere, prima azioni successive all'accesso   o la rimozione di tale elemento dalla ConcurrentLinkedDeque in un'altra   thread.

Questo comportamento implicita è un aspetto un po 'perniciosa, perché la maggior parte dei programmatori Java senza molta esperienza sarà solo prendere un sacco come dato a causa di esso. E poi improvvisamente inciampare questa discussione dopo Java non sta facendo quello che si "suppone" per fare in produzione in cui v'è un carico di lavoro diverso -. Ed è abbastanza difficile da verificare problemi di concorrenza

sincronizzato significa semplicemente che più thread se associata a singolo oggetto può impedire di lettura e scrittura sporco se blocco sincronizzato è utilizzato su particolare oggetto. Per dare più chiarezza, consente di dare un esempio:

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();
    }
}

Abbiamo creato due oggetti di classe MyRunnable, runnable1 condivisa con filetto 1 e filo 3 & runnable2 essere condiviso con il filetto 2 solo. Ora, quando t1 e t3 avvia senza sincronizzato in uso, PFB uscita che suggeriscono che entrambi i fili 1 e 3 contemporaneamente influenzano valore var dove per filo 2, var ha la propria memoria.

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

Utilizzando Synchronzied, filo 3 in attesa del filo 1 per completare in tutti gli scenari. Ci sono due blocchi acquisiti, uno su runnable1 condivisi da filo 1 e filo 3 e un altro su runnable2 condivisi da filo 2 soltanto.

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

sincronizzati mezzi semplici non esistono due thread possono accedere al blocco / metodo simultaneamente. Quando diciamo qualsiasi blocco / metodo di una classe viene sincronizzata significa solo thread possa accedere alla volta. Internamente il filo che tenta di accedervi prima rimessa blocco su quell'oggetto e finché questo blocco non è disponibile nessun altro thread può accedere qualsiasi sincronizzati metodi / blocchi di tale istanza della classe.

Nota altro thread può accedere a un metodo dello stesso oggetto che non è definito essere sincronizzati. Un thread può rilasciare il blocco chiamando

Object.wait()

sincronizzato è una parola chiave in Java che viene utilizzato per rendere accade prima relazione nel multithreading ambiente di evitare incongruenze memoria ed errori interferenza thread.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top