Geschiedenis van de kwestie
Threads (draadjes) zijn in Perl ontstaan als reactie op de behoefte aan concurrente berekeningen en parallelle toegang tot middelen in multi-task programma's. De gestandaardiseerde module threads is sinds versie 5.8 stabiel in Perl aanwezig, en is geleidelijk overgegaan van experimenten met ithreads naar de universele threads::shared.
Probleem
Het eerste probleem is dat Perl threads niet native ondersteunt zoals dat in talen zoals Java is gerealiseerd. Threads in Perl werken door de stack en de gegevens van elke thread te kopiëren, wat overhead creëert en directe toegang tot globale variabelen onmogelijk maakt (met uitzondering van variabelen met speciale binding via threads::shared). Ook garandeert Perl niet dat de threads onafhankelijk functioneren bij gelijktijdig schrijven van gegevens zonder expliciete synchronisatie.
Oplossing
Voor het organiseren van threads wordt de module threads gebruikt, en de aanvullende module threads::shared voor gegevensuitwisseling tussen threads. De verantwoordelijkheid voor synchronisatie en dataconsistentie ligt bij de ontwikkelaar, vaak door gebruik van locks.
Voorbeeldcode:
use threads; use threads::shared; my $counter :shared = 0; sub increment { lock($counter); $counter++; } my @threads; for (1..10) { push @threads, threads->create(\&increment); } $_->join for @threads; print "Counter: $counter\n";
Belangrijke kenmerken:
Is het mogelijk om globale variabelen te gebruiken zonder threads::shared en te verwachten dat threads elkaars wijzigingen zien?
Nee. Globale variabelen worden in elke thread individueel gekopieerd. Voor uitwisseling is alleen threads::shared of andere IPC (via processen) toegestaan.
Is het toegestaan om fork en threads in hetzelfde Perl-script uit te voeren?
Dit wordt afgeraden omdat het leidt tot onvoorspelbare bugs en onbetrouwbaar gedrag. Perl waarschuwt officieel voor het gelijktijdig gebruik van deze technieken.
Kan ik complexe datastructuren tussen threads doorgeven via standaardreferenties?
Nee. Perl kopieert geneste structuren niet automatisch en dergelijke pogingen leiden tot fouten of onintuitieve resultaten. Hiervoor is diepe kopiëren en het gebruik van gedeelde middelen nodig.
Een ontwikkelaar maakte een eenvoudige wachtrij via een array, gelijktijdig bijgewerkt door meerdere threads zonder threads::shared. Gegevens raakten vaak verloren en er ontstonden onjuiste resultaten.
Voordelen:
Nadelen:
Gebruik van threads::shared met locks, de gehele wachtrij werd als gedeeld gedeclareerd, synchronisatie vond plaats via lock. Het programma functioneerde stabiel, zelfs onder hoge belasting.
Voordelen:
Nadelen: