OpenJDK Project Loom

1. Áttekintés

Ebben a cikkben gyorsan áttekintjük a Project Loom-ot. Összefoglalva, a Project Loom elsődleges célja egy nagy áteresztőképességű, könnyű egyidejűségi modell támogatása a Java-ban.

2. Projekt Loom

A Project Loom az OpenJDK közösség kísérlete egy könnyű, egyidejűség-konstrukció bevezetésére a Java-ban. A Loom eddigi prototípusai változást vezettek be a JVM-ben, valamint a Java könyvtárban.

Bár a Loom számára még nincs tervezett kiadás, a legújabb prototípusokat a Project Loom wikijében érhetjük el.

Mielőtt megvitatnánk a Loom különféle fogalmait, beszéljük meg a Java egyidejűségének jelenlegi modelljét.

3. Java egyidejűségi modell

Jelenleg, cérna a párhuzamosság alapvető elvonását jelenti a Java-ban. Ez az absztrakció a többi egyidejű API-val együtt megkönnyíti az egyidejű alkalmazások írását.

Mivel azonban a Java az operációs rendszer kernelszálait használja a megvalósításhoz, nem felel meg a párhuzamosság mai követelményének. Különösen két fő probléma van:

  1. Szálak nem egyezhet a tartomány párhuzamossági egységének skálájával. Például az alkalmazások általában akár millió tranzakciót, felhasználót vagy munkamenetet engednek meg. A kernel által támogatott szálak száma azonban sokkal kevesebb. Így a Thread minden felhasználó esetében a tranzakció vagy a munkamenet gyakran nem megvalósítható.
  2. A legtöbb egyidejű alkalmazásnak szüksége van némi szinkronizálásra a szálak között minden kéréshez. Ennek köszönhetően, drága környezetváltás történik az operációs rendszer szálai között.

Az ilyen problémák lehetséges megoldása az aszinkron egyidejű API-k használata. Gyakori példák CompletableFuture és RxJava. Feltéve, hogy az ilyen API-k nem blokkolják a kernel szálát, finomabb szemcsésségű egyidejűségi konstrukciót ad az alkalmazásnak a Java szálak tetején.

Másrészről, az ilyen API-kat nehezebb hibakeresni és integrálni a régi API-kkal. Ezért szükség van egy könnyű, párhuzamos konstrukcióra, amely független a kernel szálaitól.

4. Feladatok és ütemezők

A szál bármilyen megvalósítása, akár könnyű, akár nehéz, két konstrukciótól függ:

  1. Feladat (más néven folytatás) - utasítások sorozata, amely felfüggesztheti magát valamilyen blokkolási műveletnél
  2. Ütemező - a folytatás hozzárendeléséhez a CPU-hoz és a CPU újrabeosztásához egy szünetelt folytatásból

Jelenleg, A Java az operációs rendszer megvalósításaira támaszkodik mind a folytatás, mind az ütemező számára.

A folytatás felfüggesztése érdekében a teljes hívásköteget el kell tárolni. Hasonlóképpen, folytatáskor szerezze be a hívásköteget. Mivel a folytatások operációs rendszer megvalósítása magában foglalja a natív hívásköteget a Java híváskötegével együtt, ez súlyos lábnyomot eredményez.

Nagyobb probléma azonban az OS ütemező használata. Mivel az ütemező kernel módban fut, nincs különbség a szálak között. És minden CPU kérést ugyanúgy kezel.

Ez a fajta ütemezés az nem optimális különösen a Java alkalmazásokhoz.

Vegyünk például egy alkalmazási szálat, amely végrehajt valamilyen műveletet a kérésekkel, majd továbbadja az adatokat egy másik szálnak további feldolgozás céljából. Itt, jobb lenne mindkét szálat ugyanarra a CPU-ra ütemezni. De mivel az ütemező agnosztikus a CPU-t kérő szálon, ezt lehetetlen garantálni.

A Projekt Loom ennek megoldását javasolja felhasználói módú szálak, amelyek a folytatások és ütemezők Java futásidejű végrehajtására támaszkodnak az operációs rendszer megvalósítása helyett.

5. Rostok

Az OpenJDK legújabb prototípusaiban egy új osztályt neveztek el Rost a könyvtár mellett mutatkozik be a könyvtárban cérna osztály.

A tervezett könyvtár óta Rostok hasonló cérna, a felhasználói megvalósításnak is hasonlónak kell maradnia. Két fő különbség van:

  1. Rost lenne burkoljon minden feladatot egy belső felhasználói módú folytatásba. Ez lehetővé tenné a feladat számára, hogy a kernel helyett a Java futásidejében szüneteltesse és folytassa
  2. Dugaszolható felhasználói módú ütemező (ForkJoinPool, például) használnánk

Nézzük át részletesen ezt a két tételt.

6. Folytatások

A folytatás (vagy együttes rutin) az utasítások sorozata, amelyet a hívó később adhat ki és folytathat.

Minden folytatásnak van belépési pontja és hozampontja. A hozampont az, ahol felfüggesztették. Amikor a hívó folytatja a folytatást, a vezérlő visszatér az utolsó hozamponthoz.

Fontos felismerni hogy ez a felfüggesztés / folytatás most az operációs rendszer helyett a nyelv futásidejében fordul elő. Ezért megakadályozza a drága környezetváltást a kernelszálak között.

A szálakhoz hasonlóan a Project Loom célja a beágyazott szálak támogatása. Mivel a szálak belső folytatásokra támaszkodnak, támogatniuk kell a beágyazott folytatásokat is. Ahhoz, hogy ezt jobban megértse, vegyen fontolóra egy osztályt Folytatás amely lehetővé teszi a fészkelést:

Folytatás cont1 = új Folytatás (() -> {Folytatás cont2 = új Folytatás (() -> {// valami felfüggesztés (SCOPE_CONT_2); felfüggesztés (SCOPE_CONT_1);});});

Amint a fentiekből látható, a beágyazott folytatás felfüggesztheti önmagát vagy bármelyik befogadó folytatást egy hatókör-változó átadásával. Emiatt, néven ismertek hatókörrel folytatások.

Mivel a folytatás felfüggesztése a hívásverem tárolására is szükségessé teszi, a Loom projekt célja az is, hogy a folytatás folytatása közben könnyű veremkérést adjon hozzá.

7. Ütemező

Korábban megvitattuk az OS ütemező hiányosságait a relatable szálak ugyanazon CPU-ra történő ütemezésében.

Bár a Project Loom célja, hogy lehetővé tegye a szálakkal bővíthető ütemezők használatát, ForkJoinPool aszinkron módban lesz használva alapértelmezett ütemezőként.

ForkJoinPool működik a munkalopási algoritmus. Így minden szál megőrzi a feladatot, és a fejéből hajtja végre a feladatot. Továbbá semmilyen tétlen szál nem blokkolja, várja a feladatot, és inkább egy másik szál deque-jének farkából húzza ki.

Az egyetlen különbség az aszinkron módban az a munkásszálak ellopják a feladatot egy másik deque fejétől.

ForkJoinPool hozzáad egy másik futó feladat által ütemezett feladatot a helyi sorhoz. Ezért ugyanazon a CPU-n futtatja.

8. Következtetés

Ebben a cikkben megvitattuk a Java jelenlegi egyidejűségi modelljének problémáit és a Project Loom által javasolt változásokat.

Ennek során feladatokat és ütemezőket is meghatároztunk, és megnéztük, hogyan A Fibers és a ForkJoinPool alternatívát jelenthet a Java számára a kernelszálak használatával.


$config[zx-auto] not found$config[zx-overlay] not found