Gelijktijdigheid, BlockingQueues (Java 7) - 1

"Hallo Amigo!"

"Hallo Kim!"

"Vandaag ga ik je vertellen over concurrency."

" Concurrency is een Java-klassenbibliotheek die speciale klassen bevat die zijn geoptimaliseerd voor werk vanuit meerdere threads. Dit is een zeer interessant en uitgebreid onderwerp. Maar vandaag krijgen we alleen een inleiding. Het pakket heet java.util. concurrent pakket. Ik zal je vertellen over een paar interessante lessen."

" Atomaire typen. "

"Je weet al dat zelfs count++ geen thread-safe operatie is. Wanneer een variabele met 1 wordt opgehoogd, vinden er feitelijk drie operaties plaats. Als gevolg hiervan kan er een conflict ontstaan ​​wanneer de variabele wordt gewijzigd."

"Ja, Ellie vertelde me niet lang geleden:"

Draad 1 Draad 2 Resultaat
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

'Precies. Toen voegde Java gegevenstypen toe om deze bewerkingen als één geheel uit te voeren, dwz atomair (een atoom is ondeelbaar).'

"Java heeft bijvoorbeeld AtomicInteger, AtomicBoolean, AtomicDouble , etc."

"Stel dat we een klasse «tegen» moeten maken:"

Voorbeeld
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Hoe zou je objecten van deze klasse thread-safe maken?"

"Nou, ik zou alle methoden synchroniseren en er klaar mee zijn:"

Voorbeeld
class synchronized Counter
{
 private int c = 0;

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

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

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

"Goed gedaan. Maar hoe zou het eruit zien als we atomaire typen zouden gebruiken:"

Voorbeeld
class AtomicCounter
{
 private AtomicInteger c = new AtomicInteger(0);

 public void increment()
 {
  c.incrementAndGet();
 }

 public void decrement()
 {
  c.decrementAndGet();
 }

 public int value()
 {
  return c.get();
 }
}

"Jouw klas en mijn klas werken allebei op dezelfde manier, maar de klas met een AtomicInteger werkt sneller."

"Nou, is het een klein verschil?"

"Ja. Op basis van mijn ervaring raad ik altijd aan om te leiden met gesynchroniseerd. Pas als alle applicatiecode is geschreven en het optimalisatieproces is begonnen, moet je beginnen met het herschrijven van de code om de atomaire typen te gebruiken. Maar hoe dan ook, ik wilde je om te weten dat dergelijke typen bestaan. Zelfs als je ze niet actief gebruikt, is er altijd een kans dat je code tegenkomt waar ze worden gebruikt.'

"Ik ben het ermee eens. Dat is logisch."

"Trouwens, heb je gemerkt dat de atomaire typen niet onveranderlijk zijn ? In tegenstelling tot de standaard Integer- klasse bevat AtomicInteger methoden om de interne status te wijzigen."

"Begrepen. Net als String en StringBuffer ."

"Ja, zoiets."

" Draadveilige collecties. "

"Als voorbeeld van zo'n verzameling, mag ik ConcurrentHashMap presenteren. Hoe zou je HashMap thread-safe maken?"

"Al zijn methoden synchroniseren?"

"Natuurlijk, maar stel je nu voor dat je zo'n SynchronizedHashMap hebt en tientallen threads die er toegang toe hebben. En honderd keer per seconde wordt er een nieuw item aan de kaart toegevoegd, en tijdens het proces wordt het hele object vergrendeld voor lezen en schrijven."

"Nou, dit is de standaard aanpak. Wat kun je doen?"

"De makers van Java hebben een paar coole dingen bedacht."

"Ten eerste slaan ze gegevens op in een ConcurrentHashMap in een enkel blok, maar verdelen het in delen die 'buckets' worden genoemd. En wanneer iemand gegevens wijzigt in een ConcurrentHashMap, dan vergrendelen we alleen de bucket waartoe toegang wordt verkregen, in plaats van het hele object. In andere woorden, veel threads kunnen het object tegelijkertijd veranderen."

"Ten tweede, weet je nog dat je de elementen van de lijst/kaart niet kunt herhalen en tegelijkertijd de lijst kunt wijzigen? Dergelijke code zal een uitzondering opleveren:"

Herhaal de elementen van een verzameling niet in een lus en wijzig deze tegelijkertijd
HashMap<String, Integer> map = new HashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Maar in ConcurrentHashMap kunt u:"

Herhaal de elementen van een collectie niet in een lus en wijzig deze tegelijkertijd"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Het gelijktijdige pakket heeft veel voordelen. We moeten deze klassen alleen heel goed begrijpen om ze te kunnen gebruiken."

"Ik begrijp het. Bedankt, Kim. Dit zijn echt interessante lessen. Ik hoop dat ik ze ooit als een virtuoos onder de knie zal krijgen."