Mi a különbség az egyetlen szál és a több szál között?


Legjobb válasz

A kérdésre adott válasz a következő: megegyezik a “szál” különbségével “és” sok “.

De úgy gondolom, hogy valójában mire gondoltál, valami ilyesmi: miben különböznek a programozási módszertanok egyetlen szál egyetlen programban történő programozásához képest, több szál egyetlen programban történő programozásához képest folyamat?

Könyveket írtak a témáról. De nagyon röviden, a különbségek mind egy tényezőhöz kapcsolódnak: amikor egyetlen szálon és folyamaton programoz, mindig tudja, hogyan jutott el az aktuális utasításhoz. Az utasítások egyetlen sorrendben fordulnak elő. De ha sok szálra programoz, akkor fogalma sincs arról, hogy mely utasításokat milyen sorrendben hajtották végre, hogy eljusson az aktuális utasításhoz. Ez bonyolultabbá teszi a programozást.

De még egy tényező bonyolítja: a folyamatokkal ellentétben a szálak megosztják a memóriát. Nem tudja, melyik szál érintette meg utoljára az adott memóriahelyet, vagy melyik lesz a következő, hacsak nem rendelkezik valamilyen “szinkronizálással”. Ezért a “szinkronizált” kulcsszó a Java-ban (az Adától leszakítva). Monitorok, szemaforok, zárak , feltételváltozókat és még az üzenet továbbítását is használták a szinkronizáláshoz.

Válasz

(Frissítés: Vigyázzon egy másik válaszra, amely szerint nem lehet egyszálú webszerver, amely jól kezeli az egyidejű kéréseket, mert ez egyszerűen nem igaz.)

Miért jobb egy többszálú webszerver, mint egyszálas szerver? Nem az.

Négy alapvető módja van annak, hogy a webszerver kezelje az egyidejűséget:

  1. villás operációs rendszer folyamat kérésenként (például az Apache régi verziói)
  2. operációs rendszer szál létrehozása kérésenként (például az Apache új verziói)
  3. egyszálas eseményhurok (például nginx) használatával )
  4. zöld szálak vagy könnyű folyamatok felhasználásával az operációs rendszer helyett egy virtuális gép futásideje ütemezi (mint például az Erlangban)

Jelenleg a leggyakoribb megközelítések a 2. és a 3. szám. tőlük. A I / O-kötött műveletekhez (egy tipikus webszerver jellemzője) jobb teljesítményt kap és nagyobb számú egyidejű kérés , ha egyszálú eseményhurkot használ. De hátránya, hogy minden művelethez kizárólag aszinkron nem blokkoló I / O-t kell használnia, különben blokkolja az eseményhurkot és elveszíti a teljesítményét. Ezért könnyebb megvalósítani a többszálas kiszolgálót, de a teljesítményért fizet.

A CPU-hoz kötött műveletekhez (kevésbé jellemző a egy szokásos webkiszolgáló, amely egy számítási szempontból intenzív API esetében talán gyakoribb) a legjobb, ha magonként egy operációs rendszer szál vagy folyamat van . Könnyű megtenni egyszálú eseményhurokkal, mert magonként számos folyamat fürtjét futtathatja. Nehéz megtenni a többszálú szerverekkel, mert ha az ívó szálak az egyetlen módja az egyidejű kérések kezelésének, akkor nem igazán tudja szabályozni, hogy hány szála lesz – mivel nem Ön ellenőrzi a kérések számát. Ha több szál van, mint a CPU-magok száma, akkor elveszíti a teljesítményét a környezetkapcsolók esetében, és sok RAM-ot is használ.

Ezért van az, hogy egy egyszálú nginx szerver jobban teljesít, mint egy többszálú Apache webszerver (és ezért jött létre először az nginx). Szintén Redis , a kivételesen nagy teljesítményről ismert adatbázis egyszálú .

Valódi példát tudok mondani a következőkről: Az első webszerverem az Apache volt, amely Linux gépen fut, 500 MB RAM-mal. Minden kéréshez új folyamatot rendelt el (valójában volt poolja, így nem volt sok elágazás, de életben kellett tartania ezeket a folyamatokat, hogy újra felhasználhassa őket, és egyszer-egyszer megölje őket az erőforrások szivárgásának elkerülése érdekében.

Az operációs rendszerem kb. 100 MB RAM-ot használt fel. Minden Apache folyamat 20 MB RAM-ot használt fel. Ez azt jelentette, hogy a szerverem csak 20 egyidejű kérést tudott kezelni, és nem volt megkerülhető, mert nem volt több RAM. A folyamatokat többnyire az I / O-n blokkolták, így a CPU kihasználtsága nagyon alacsony volt, minden kérelemnek a 20 fölött kellett várnia, és ha ez a 20 pl. hosszú futó letöltések, akkor a szerverem teljesen nem reagált.

Az nginx webszerver bevezetésekor egyszálú eseményhurokot használt, és nem blokkolt semmilyen kérést. Sokkal több egyidejű kérést tud kezelni, nem okoz problémát a mitikus c10k problémával – az nginx alapvetően a c10k probléma (10 000 egyidejű kérés) megoldására jött létre.

Képzelje el, mennyi RAM-ot pazarolnak el 10 000 szálra, ha akár annyi és mennyi időt is igénybe vehet a kontextusváltásra.

Többszálas Apache és egyszálú nginx memóriahasználata:

Egyébként ez az oka annak, hogy Ryan Dahl nem blokkoló I / O-t és egyszálú eseményhurkot használt a Node.js-ben, és Deno-ban még mindig ugyanazt az ötletet használja, mert így írhatunk nagy teljesítményű hálózati szervereket (ellentétben azzal, amit itt más válaszokban olvashatunk).

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük