Threads are bad?

Fórumok

Előrelátóan a Flame kategóriába helyeztem... :)

Suckit blogján található a következő bejegyzés:

Threads were invented as a very bad workaround for slow context
switching on ancient hardware using primitive OS versions.
The people who invented them said they were bad.
Any teacher or programmer who says otherwise is ignorant.
There's a paper from Berkeley showing how a threaded program can
never be fully debugged and should be presumed to be broken,
probably fatally broken.

geoff steckel

Ez véleményem szerint kicsit túl általános kijelentés. Nem látom, hogy egy olyan threadelt program, ahol a threadek csak jól meghatározott, threadsafe interfészen (pl. threadsafe queue-k) keresztül kommunikálnak, miért nem debuggolható teljesen, és miért ne lehetne akár formálisan is bizonyítani a helyes működést.

A multiprocessz programoknak természetesen sok előnye van robusztusság szempontjából, de a kommunikációnak mindig lesz overheadje a threadekhez képest. Itt nem csak a context-switch-re gondolok, hanem arra, hogy komplex adatok átadásánál szerializálni kell a küldéshez. Az a felhasználástól függ, hogy ez az overhead elfogadható-e, vagy nem.

Nektek mi a véleményetek?

Hozzászólások

Ha valakit netan erdekel a paper:

http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf

A kizarolag threadsafe queue-kon keresztuli mukodes nagyjabol a message passingnak felel meg. Nezz meg egy 'hatekony', mutexekkel megpakolt programot, avagy azt, amikor trukkozol a kulonbozo message loopok aszinkron mukodesevel (komolyabb GUI programozasnal eleg sokszor elojon a problema).

----------------------
while (!sleep) sheep++;

Átfutottam a papert, és egyetértek vele (amennyire volt időm megnézni). De a paper konklúziója szerintem nem az, hogy "threads are bad", hanem, hogy a threadek használatához olyan frameworköt kell nyújtani, mint pl. a java.util.concurrent, ami lehetőleg programozóbiztossá teszi a használatukat.

Tehát a hivatkozott paper csak megerősíti azt, hogy a topicindítóban hivatkozott idézet valójában nem igaz.

A közös memóriatér jelentős előny lehet a "message passing" szerű threadek közötti kommunikációnál is: Nem mindegy, hogy egy sokezer objektumból álló modellt simán referenciaként át tudsz adni egy threadnek, vagy szerializálgatnod kell oda-vissza.

Szarul megírt multithreades programot szerintem mindenki látott, sőt, aki komolyabban programozik, az már írt is...

Üdv,
Gergely

Az util.concurrent nem old meg semmit, velemenyem szerint. A jol szegmentalhato problemakra ad utility osztalyokat, kb. mint a .Net 4.0 task libraryje. Ja, meg threadsafe kollekciok, az sem sokat jelent, attol, hogy az adatstruktura maga nem esik szet, meg a problema fentall.

Keressetek ra a composable transaction-okre.

----------------------
while (!sleep) sheep++;

De a paper konklúziója szerintem nem az, hogy "threads are bad",
Igen, sőt a fenti blogbejegyzéssel az a baj, hogy azt sugallja, hogy rendszertechnikailag rosszak a szálak (nincs alternatívájuk, folyamaton belül párhuzamosság szálakon kívül csak SIMD-vel lehetséges, viszont az teljesen más feladatokra alkalmazható), ezzel szemben a cikk kifejezetten a programozói konstrukciók problémáiról szól.

hanem, hogy a threadek használatához olyan frameworköt kell nyújtani, mint pl. a java.util.concurrent, ami lehetőleg programozóbiztossá teszi a használatukat.
Továbbmennék, szerintem inkább a hangsúly azon van, hogy a programozó felé már nyelvi szinten más modellt kell prezentálni, amiből egyrészt jobban átlátható a konkurencia és a nemdeterminisztikus futási lehetőségek, másrészt közelebb is áll a formális modellekhez, amikkel vizsgálni lehet ezeket.
---
Internet Memetikai Tanszék

Nem olvastam el Edward A. Lee írását (legalábbis most nem). A szálak teljes elutasítását mindenesetre nem tartom indokoltnak. Én inkább így fogalmaznék: jobban jársz, ha explicit szálkezelést csak akkor alkalmazol, amikor már minden más alternatívát (aio-t, szinkron multiplexelést, utóbbiba beleértve a GUI-t is) megfontoltál és elvetettél. A szálprogramozás véleményem szerint nagyon nagy fegyelmet, visszafogottságot, formális hozzáállást, és nagyon kicsi (lehetőleg egyszemélyes) fejlesztői csapatot igényel.

Azzal egyetértek, hogy ha kétségeid vannak, akkor inkább ne használj explicit szálakat.

Néhány mondás:

  • Lehetőleg ne feladattípusonként csinálj szálakat (heterogén szálak). Homogén szálakat készíts, amelyek egymással csereszabatosak és a lehető legtöbb feladatot el tudják látni, "ami éppen adódik".
  • Az előző folyományaként a feladatokhoz rendelj prioritást, ne a szálakhoz.
  • A kód felbontása akkor jó, ha (értelmes korlátok között) kétszer annyi magon minden további nélkül el lehet indítani, és érdemes is elindítani kétszer annyi dolgozó szálat.
  • Ha már egyszer muszáj szálakat használni, ne próbálj a zároláson spórolni. A spinlock-okkal, volatile-lal, atomics-szal bohóckodásnak az esetek 99%-ában rossz vége van. (A volatile-nak C-ben ill. C++-ban definíció szerint semmi köze sincs a szálakhoz, mivel ezek a nyelvek (a jelenleg érvényes szabványaik) nem ismerik a szálak fogalmát.) Használd a legdurvább zárfelbontást, amit csak tudsz. Mind a zárolási műveletek költségét, mind a zárakért való versengést az egyes feladatok számításigényéhez viszonyítva érdemes vizsgálni.
  • Lehetőleg ne írj, és ne is használj olyan library-t, amely a kliens programozóval való előzetes egyeztetés nélkül fork-ol vagy szálat indít.

A "szálak vagy processzek" kérdéshez: szerencsés esetben eldönthető az elején, hogy mekkorára akarunk nőni. Ha a cluster már az elején is látszik, akkor nyilván processzek, és esetleg csinálhatunk egy shm-re alapuló transzportot, hogy valamennyit megspóroljunk a szerializációból gépen belül. De ez igazából ilyenkor mindegy; ha több gépre lövünk, akkor nem bánjuk, hogy egy gépből pár százalékot elvisz a transzport CPU igénye.

A szálak mellett akkor érdemes dönteni a processzek ellenében, ha (1) feltétlenül osztott memória kell (bár ezt is meg lehet oldani éppen processzekkel, csak talán kényelmetlenebbül), vagy ha (2) tudjuk, hogy sohasem lesz szükségünk több gépre, vagy ha (3) kifejezetten egyetlen processzben akarunk maradni valamilyen oknál fogva. (Az első két esetben még mindig beválhat a processzekre bontás, mert a processzeket védi egymástól a kernel, és az osztozkodás a kivétel -- a szálaknál a legtöbb dolog közös, és a "magánjellemző" a kivétel.)