Java >> Java tutorial >  >> Java

I Java, hvad er forskellen mellem en skærm og en lås

Fra den officielle dokumentation for låse og synkronisering:

  • Synkronisering er bygget op omkring en intern enhed kendt som intrinsic lock eller skærmlås . (API-specifikationen refererer ofte til denne enhed blot som en "monitor")
  • Hvert objekt har en iboende lås knyttet til sig. Efter konvention skal en tråd erhverve objektets skærmlås før du får adgang til dem, og slip derefter skærmlåsen når det er færdigt med dem. En tråd siges at eje låsen mellem det tidspunkt, hvor den har erhvervet låsen og frigivet låsen. Så længe en tråd ejer en skærmlås, kan ingen anden tråd få den samme lås. Den anden tråd vil blokere, når den forsøger at hente låsen.
  • Når en tråd udløser låsen, etableres en sker-før-relation mellem den handling og enhver efterfølgende erhvervelse af den samme lås.

Så en skærm og en lås kan ikke sammenlignes for forskelle, de er snarere komplementære til hinanden. Hvert objekt i Java er forbundet med en skærm, som en tråd kan låse eller lås op .


Låse

En lås er en slags data, som logisk er en del af et objekts header på heap-hukommelsen. Hvert objekt i en JVM har denne lås (eller mutex), som ethvert program kan bruge til at koordinere multi-threaded adgang til objektet. Hvis en tråd ønsker at få adgang til instansvariabler for det objekt; så skal tråden "eje" objektets lås (sæt et eller andet flag i låsehukommelsesområdet). Alle andre tråde, der forsøger at få adgang til objektets variabler, skal vente, indtil ejertråden frigiver objektets lås (fjern flaget).

Når først en tråd ejer en lås, kan den anmode om den samme lås igen flere gange, men skal derefter frigive låsen det samme antal gange, før den gøres tilgængelig for andre tråde. Hvis en tråd for eksempel anmoder om en lås tre gange, vil den tråd fortsætte med at eje låsen, indtil den har "frigivet" den tre gange.

Bemærk venligst, at låsen erhverves af en tråd, når den udtrykkeligt beder om det. I Java gøres dette med det synkroniserede nøgleord, eller med wait and notify.

Monitorer

Monitor er en synkroniseringskonstruktion, der gør det muligt for tråde at have både gensidig udelukkelse (ved hjælp af låse) og samarbejde, dvs. evnen til at få tråde til at vente på, at en bestemt betingelse er sand (ved at bruge wait-set).

Med andre ord, sammen med data, der implementerer en lås, er hvert Java-objekt logisk forbundet med data, der implementerer et ventesæt. Mens låse hjælper tråde med at arbejde uafhængigt på delte data uden at forstyrre hinanden, hjælper ventesæt tråde med at samarbejde med hinanden for at arbejde sammen mod et fælles mål, f.eks. alle ventende tråde vil blive flyttet til dette ventesæt, og alle vil blive underrettet, når låsen er frigivet. Dette ventesæt hjælper med at bygge skærme med yderligere hjælp af lås (mutex).

For mere afklaring se -

FORSTÅ TRÅDER, MONITORER OG LÅSE

Forskel mellem lås og skærm – Java Concurrency


Dokumentet https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html er måske ikke et særlig godt sted at finde ud af forskellen mellem lås og skærm, især de termer, den nævnte:intrinsic lock , monitor lock og blot monitor , hvilket tyder på, at skærm og lås er udskiftelige.

Dette er ikke sandt.

Monitor er en struktur, der bruges til flertrådssynkronisering. Den består af en lås og flere tilstandsvariable. En betingelsesvariabel er en kø, som tråde kan sætte dem på, når en given betingelse ikke er som ønsket. En anden tråd kan vække disse tråde, når den gør tilstanden sand. Condition Variable er en måde, der hjælper tråde med at samarbejde med hinanden.

I simple synkroniseringstilfælde gør vi kun brug af den lås, som skærmen har leveret, som dette eksempel:

class SimpleCase {
  int counter;

  synchronized inc() int {
    return counter++;
  }
} 

Tråde udfører inc() behøver intet samarbejde, kun lås er nødvendig for at få trådene til at udelukke hinanden, hvilket gør counter trådsikker.

Mens i mere komplicerede tilfælde er der ikke kun behov for gensidig udelukkelse (mutex), men også samarbejde.

For eksempel det afgrænsede forbruger/producent-problem:multiforbrugere og producenter forbruger og sender beskeder til en kø. Der er behov for samarbejde, fordi beskedkøen har en maksimal størrelse, når køen er fuld, kan der ikke sendes flere beskeder, og når køen er tom, kan der ikke forbruges flere beskeder.

Nedenfor er koden, der viser producenten:

package monitor;

public class Producer {
    BoundedQueue queue;

    public Producer(BoundedQueue queue) {
        this.queue = queue;
    }

    public void send(int msg) throws InterruptedException {
        synchronized (queue) {
            // wait till there is room to produce
            while (queue.isFull()) {
                queue.wait();
            }

            // business logic here
            queue.add(msg);
            System.out.println("sent:" + msg + ", from:" + Thread.currentThread().getName());

            // before exit, call notify() to wake up waiting threads
            queue.notifyAll();
        }// implicit release the lock when exiting the synchronized block
    }
}

I koden er BoundedQueue bruges som monitor, bortset fra gensidig udelukkelse, har producenter og forbrugere også brug for samarbejde:når køen er fuld, skal producenterne wait() , og når køen har ledige pladser, skal producenterne underrettes for at vågne op fra ventetiden, efter at producenten har sendt data til køen, skal den også ringe til notifyAll() i tilfælde af at der er forbrugere, der venter på betingelsen om, at køen ikke er tom.

Her er muligheden for at wait og notify leveres af Monitor for at få tråde til at samarbejde.

Håber dette hjælper dig med at forstå forskellen mellem Monitor og Lock.

Ref:

  • https://en.wikipedia.org/wiki/Monitor_(synkronisering)
  • http://pages.cs.wisc.edu/~remzi/OSTEP/threads-cv.pdf

Java tag