Samtidighed, blokeringskøer (Java 7) - 1

"Hej, Amigo!"

"Hej Kim!"

"I dag vil jeg fortælle dig om samtidighed."

" Concurrency er et Java-klassebibliotek, der inkluderer specielle klasser, der er optimeret til arbejde fra flere tråde. Dette er et meget interessant og omfattende emne. Men i dag skal vi lige få en introduktion. Pakken hedder java.util. samtidig pakke. Jeg vil fortælle dig om et par interessante klasser."

" Atomtyper. "

"Du ved allerede, at selv count++ ikke er en trådsikker operation. Når en variabel øges med 1, finder der faktisk tre operationer sted. Som følge heraf kan der opstå en konflikt, når variablen ændres."

"Ja, Ellie fortalte mig for ikke længe siden:"

Tråd 1 Tråd 2 Resultat
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Nøjagtigt. Så tilføjede Java datatyper for at udføre disse operationer som én, dvs. atomært (et atom er udeleligt)."

"For eksempel har Java AtomicInteger, AtomicBoolean, AtomicDouble osv."

"Antag, at vi skal lave en "tæller"-klasse:"

Eksempel
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Hvordan ville du gøre objekter af denne klasse trådsikre?"

"Nå, jeg ville gøre alle metoderne synkroniserede og være færdige med det:"

Eksempel
class synchronized Counter
{
 private int c = 0;

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

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

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

"Godt arbejde. Men hvordan ville det se ud, hvis vi brugte atomtyper:"

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

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

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

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

"Din klasse og min klasse arbejder begge på samme måde, men klassen med et AtomicInteger fungerer hurtigere."

"Nå, er det en lille forskel?"

"Ja. Baseret på min erfaring anbefaler jeg altid at lede med synkroniseret. Først når al ansøgningskoden er skrevet og optimeringsprocessen er begyndt, bør du begynde at omskrive koden til at bruge atomtyperne. Men under alle omstændigheder ville jeg have dig at vide, at sådanne typer findes. Selvom du ikke aktivt bruger dem, er der altid en chance for, at du løber ind i kode, hvor de bruges."

"Jeg er enig. Det giver mening."

"Lagde du i øvrigt mærke til, at atomtyperne ikke er uforanderlige ? I modsætning til standard Integer- klassen indeholder AtomicInteger metoder til at ændre dens indre tilstand."

"Forstår det. Ligesom String og StringBuffer ."

"Ja, sådan noget."

" Trådsikre samlinger. "

"Må jeg som eksempel på en sådan samling præsentere ConcurrentHashMap. Hvordan ville du gøre HashMap trådsikker?"

"Gøre alle dets metoder synkroniseret?"

"Selvfølgelig, men forestil dig nu, at du har sådan et SynchronizedHashMap, og dusinvis af tråde, der får adgang til det. Og hundrede gange i sekundet tilføjes en ny post til kortet, og i processen låses hele objektet til læsning og skrivning."

"Nå, dette er standardtilgangen. Hvad kan du gøre?"

"Javas skabere fandt på et par fede ting."

"For det første gemmer de data i et ConcurrentHashMap i en enkelt blok, men deler det op i dele kaldet 'buckets'. Og når nogen ændrer data i et ConcurrentHashMap, så låser vi kun den bucket, der tilgås, i stedet for hele objektet. I andre ord, mange tråde kan ændre objektet samtidigt."

"For det andet, kan du huske, at du ikke kan iterere over elementerne i listen/kortet og ændre listen på samme tid? En sådan kode vil give en undtagelse:"

Gentag ikke elementerne i en samling i en løkke og skift den samtidig
HashMap<String, Integer> map = new HashMap<String, Integer>();

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

"Men i ConcurrentHashMap kan du:"

Lad være med at gentage elementerne i en samling i en løkke og ændre den samtidigt"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

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

"Den samtidige pakke har mange fordele. Vi skal bare forstå disse klasser meget godt for at kunne bruge dem."

"Jeg forstår det. Tak, Kim. Det er virkelig interessante klasser. Jeg håber, at jeg en dag vil mestre dem som en virtuos."