2015-12-30 10 views
8

W Javie 8, java.lang.Thread klasa dostaje 3 nowe pola:Nowe dodatkowe pola w java.lang.Thread, jaki jest pomysł?

/** The current seed for a ThreadLocalRandom */ 
@sun.misc.Contended("tlr") 
long threadLocalRandomSeed; 

/** Probe hash value; nonzero if threadLocalRandomSeed initialized */ 
@sun.misc.Contended("tlr") 
int threadLocalRandomProbe; 

/** Secondary seed isolated from public ThreadLocalRandom sequence */ 
@sun.misc.Contended("tlr") 
int threadLocalRandomSecondarySeed; 

jak to powiedział w Javadoc dla zarządzana wyłącznie przez klasę java.util.concurrent.ThreadLocalRandom.

Ponadto w ThreadLocalRandom są one wykorzystywane w bardzo dziwaczny sposób:

SEED = UNSAFE.objectFieldOffset 
    (tk.getDeclaredField("threadLocalRandomSeed")); 
PROBE = UNSAFE.objectFieldOffset 
    (tk.getDeclaredField("threadLocalRandomProbe")); 
SECONDARY = UNSAFE.objectFieldOffset 
    (tk.getDeclaredField("threadLocalRandomSecondarySeed")); 

(ten sam kawałek kodu może być spełnione również w LockSupport klasie).

, a następnie te przesunięcia są używane wewnętrznie w kilku miejscach java.concurrent.

Jaka jest idea? Dlaczego te pola są miejscami wewnątrz java.lang.Thread? Dlaczego nie wewnątrz ThreadLocalRandom?

+2

Nie mam pojęcia o tym - miałbym/faktycznie miałem odpowiedź na twoje poprzednie pytanie dotyczące '" tlr "'. – luk2302

+0

@ luk2302 Świetna odpowiedź, bardzo ci dziękuję, ale ktoś źle ocenił moje pytanie, więc muszę je usunąć. Naprawdę przepraszam za to. – Andremoniy

+2

Downvotes nie są powodem do usuwania pytań lub odpowiedzi, na przykład dałem ci uprowadzenie, co daje wynik 0. – luk2302

Odpowiedz

6

To są pola wewnętrzne. Wyjaśnienia mogą pochodzić wyłącznie od programistów JDK. Udało mi się znaleźć na ten temat post z Doug Lea z stycznia 2013 r., Która wyjaśnia powody tych pól i dlaczego są one w klasie Thread.

Kiedy wprowadziliśmy ThreadLocalRandom konserwatywnie realizowany jest w użyciu rzeczywistej ThreadLocal. Jednak, gdy staje się on coraz szerzej wykorzystywany, warto ulepszyć implementację przez obudowę ThreadLocalRandom stan (i związane z nią księgowanie) w samej klasie Thread. Wymagałoby to trzech pól (16 w sumie bajtów).

Więc proponujemy dodanie następujących do klasy Temat:

// The following three initially uninitialized fields are exclusively 
// managed by class java.util.concurrent.ThreadLocalRandom. 
/** The current seed for a ThreadLocalRandom */ 
long threadLocalRandomSeed; 
/** Probe hash value; nonzero if threadLocalRandomSeed initialized */ 
int threadLocalRandomProbe; 
/** Secondary seed isolated from public ThreadLocalRandom sequence */ 
int threadLocalRandomSecondarySeed; 

Przyczyny robi to w ten sposób to:

  1. Równomiernie szybszy dostęp do ThreadLocalRandom stan. Choć ThreadLocal dostępu jest już zazwyczaj dość szybko, to jest nie tylko szybsze , nie ulega degradacji w przypadkach, gdy użytkownik programy tworzą dużą liczbę ThreadLocal s, co może (probabilistycznie) powoduje daną dostęp stać wolniej.

  2. Mniejszy całkowity ślad dla dowolnego programu przy użyciu ThreadLocalRandom. Trzy pola wymagają mniej miejsca niż boks na wyściełany obiekt ThreadLocal. Ponieważ ThreadLocalRandom staje się szeroko stosowany w samym JDK, obejmuje to prawie wszystkie programy.

  3. Dalsze oszczędności czasu/przestrzeni dla java.util.concurrent ForkJoinPool, ConcurrentHashMap, LongAdder, ConcurrentSkipList i inne klas, które mogłyby korzystać z tej formy ujednoliconej ThreadLocalRandom księgowości zamiast własnej specjalnego przeznaczenia ThreadLocal ów jak oni teraz zrobić.

+0

Dziękuję bardzo za link do papieru, +1. Ale to rozwiązanie wygląda na nieco niechlujne, nie sądzisz? – Andremoniy

+0

Ponadto, tak naprawdę nie rozumiem, dlaczego te pola nie mogą być umieszczone w klasie 'ThreadLocalRandom'? – Andremoniy

+2

@Andremoniy Szczerze mówiąc, nie jestem w stanie ocenić rozwiązań technicznych dokonanych przez samych twórców JDK. Przyczyna, dla której zostały one dodane do wątku prawdopodobnie sprowadza się do tego komentarza Douga Lea: "Ale głównie: Miejsce dla" stałych "mieszkańców nitek trzeba gdzieś umieścić, dlaczego nie wybrać miejsca, które przedstawia najmniej problemów logistycznych? Należy zauważyć, że klasa java.lang.Thread jest tylko widoczną końcówką góry lodowej pamięci wątków na systemach , więc dodanie 16 bajtów jest prawie niewykrywalne. " – Tunaki

1

będę wskrzesić to przez dodanie małej odpowiedź też, odkąd tylko hit to w LongAdder i tam świetny film gdzie Shipilev wyjaśnia to w prostych słowach (jest w języku rosyjskim), tutaj jest Łącze: ThreadLocalRandom

W przypadku ForkJoinPool, musi umieścić zadania w kolejce i usunąć z kolejki, która to kolejka exaclty jest rozwiązana przez dobre PRNG.

Ten prng musi być bardzo szybki i wysoce skalowalny. Cóż, java ma jedną na swoim miejscu: ThreadLocalRandom. Aby te pola mogły zostać umieszczone w ThreadLocalRandom, potrzebne było ThreadLocal, które z kolei używa wewnętrznie ThreadLocalMap (think HashMap).

ThreadLocal.get (think HashMap # get) jest znacznie wolniejszy niż pobieranie tych pól bezpośrednio z wątku.

Powiązane problemy