"Cześć, Amigo!"
"Cześć, Kim!"
„Dzisiaj opowiem wam o współbieżności”.
" Concurrency to biblioteka klas Java, która zawiera specjalne klasy, które zostały zoptymalizowane do pracy z wieloma wątkami. To bardzo ciekawy i obszerny temat. Ale dzisiaj dostaniemy tylko wprowadzenie. Pakiet nazywa się java.util. pakiet równoległy. Opowiem o kilku ciekawych zajęciach."
„ Typy atomowe ” .
„Wiesz już, że nawet count++ nie jest operacją bezpieczną dla wątków. Kiedy zmienna jest zwiększana o 1, w rzeczywistości mają miejsce trzy operacje. W rezultacie może wystąpić konflikt, gdy zmienna zostanie zmieniona”.
„Tak, Ellie powiedziała mi nie tak dawno temu:”
Wątek 1 | Wątek 2 | Wynik |
---|---|---|
|
|
|
„Dokładnie. Następnie Java dodała typy danych, aby wykonywać te operacje jako jeden, tj. atomowo (atom jest niepodzielny).”
„Na przykład Java ma AtomicInteger, AtomicBoolean, AtomicDouble itp.”
„Załóżmy, że musimy stworzyć klasę «licznik»:”
class Counter
{
private int c = 0;
public void increment()
{
c++;
}
public void decrement()
{
c--;
}
public int value()
{
return c;
}
}
„Jak sprawić, by obiekty tej klasy były bezpieczne dla wątków?”
„Cóż, zsynchronizowałbym wszystkie metody i skończyłbym z tym:”
class synchronized Counter
{
private int c = 0;
public synchronized void increment()
{
c++;
}
public synchronized void decrement()
{
c--;
}
public synchronized int value()
{
return c;
}
}
„Dobra robota. Ale jak by to wyglądało, gdybyśmy używali typów atomowych:”
class AtomicCounter
{
private AtomicInteger c = new AtomicInteger(0);
public void increment()
{
c.incrementAndGet();
}
public void decrement()
{
c.decrementAndGet();
}
public int value()
{
return c.get();
}
}
„Twoja klasa i moja klasa działają w ten sam sposób, ale klasa z AtomicInteger działa szybciej”.
– No, czy to mała różnica?
„Tak. Bazując na moim doświadczeniu, zawsze zalecam prowadzenie z synchronizacją. Dopiero po napisaniu całego kodu aplikacji i rozpoczęciu procesu optymalizacji należy zacząć przepisywać kod, aby używał typów atomowych. Ale w każdym razie chciałem, żebyś wiedzieć, że takie typy istnieją. Nawet jeśli nie używasz ich aktywnie, zawsze istnieje szansa, że natrafisz na kod tam, gdzie są używane”.
„Zgadzam się. To ma sens”.
„Przy okazji, czy zauważyłeś, że typy atomowe nie są niezmienne ? W przeciwieństwie do standardowej klasy Integer , AtomicInteger zawiera metody zmiany swojego stanu wewnętrznego”.
„Rozumiem. Tak samo jak String i StringBuffer ”.
"Tak, coś w tym stylu."
„ Kolekcje bezpieczne dla wątków ” .
„Jako przykład takiej kolekcji mogę przedstawić ConcurrentHashMap. Jak sprawić, by HashMap był bezpieczny dla wątków?”
„Zsynchronizować wszystkie jego metody?”
„Oczywiście, ale teraz wyobraź sobie, że masz jedną taką SynchronizedHashMap i dziesiątki wątków uzyskujących do niej dostęp. I sto razy na sekundę do mapy dodawany jest nowy wpis, a w trakcie tego procesu cały obiekt jest blokowany do odczytu i zapisu”.
„Cóż, to jest standardowe podejście. Co możesz zrobić?”
„Twórcy Javy wymyślili kilka fajnych rzeczy”.
„Po pierwsze, przechowują dane w ConcurrentHashMap w jednym bloku, ale dzielą je na części zwane„ segmentami ”. A kiedy ktoś zmienia dane w ConcurrentHashMap, blokujemy tylko dostęp do segmentu, a nie cały obiekt. słowa, wiele wątków może jednocześnie zmieniać obiekt”.
„Po drugie, czy pamiętasz, że nie możesz iterować elementów listy/mapy i jednocześnie zmieniać listy? Taki kod rzuci wyjątek:”
HashMap<String, Integer> map = new HashMap<String, Integer>();
for (String key: map.keySet())
{
if (map.get(key) == 0)
map.remove(key);
}
„Ale w ConcurrentHashMap możesz:”
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
for (String key: map.keySet())
{
if (map.get(key) == 0)
map.remove(key);
}
„Pakiet równoległy ma wiele zalet. Musimy tylko bardzo dobrze zrozumieć te klasy, aby z nich korzystać”.
„Rozumiem. Dzięki, Kim. To naprawdę ciekawe zajęcia. Mam nadzieję, że kiedyś opanuję je jak wirtuoz”.
GO TO FULL VERSION