Multitasking is een methode om één processor schijnbaar meerdere taken (programma's of delen daarvan) tegelijkertijd te laten uitvoeren (zie ook gedistribueerd programmeren). Het besturingssysteem wisselt zeer snel tussen de verschillende actieve programma's. Deze omschakelingen, context switches, kunnen geheel vrijwillig door het draaiende proces geïnitieerd worden of door een externe gebeurtenis zoals een hardware-interrupt (een verzoek tot het verkrijgen van processortijd).
In de jaren 60 ondernamen onderzoekers de eerste pogingen om multitaskingsystemen te creëren. Dit heette toentertijd "tijdscharing" omdat het doel was om verschillende gebruikers tegelijkertijd gebruik te kunnen laten maken van een mainframe zodat de bruikbaarheid hiervan toenam. De uitdrukking "tijdscharing" is in onbruik geraakt ten voordele van het meer algemene "multitasking".
De allereerste multitaskingsystemen bestonden uit een reeks gerelateerde programma's die vrijwillig de processor aan elkaar vrijgaven. Deze aanpak, die uiteindelijk door verschillende besturingssystemen werd gebruikt, kennen we vandaag als coöperatieve multitasking. Hoewel het tegenwoordig zelden in grotere systemen gebruikt wordt, gebruikte de eerste versie van Amiga OS het in 1985, net als RISC OS anno 1987. Ook Microsoft Windows in de versies voor Windows 95 en Mac OS in de versies voorafgaand aan Mac OS X maakten gebruik van deze vorm van multitasking.
Coöperatieve multitasking kent verschillende tekortkomingen. Een dergelijk systeem vertrouwt er namelijk op, dat elk programma op het systeem regelmatig vrijwillig de processor vrijgeeft voor andere processen. Een slecht ontworpen programma of een programma dat "hangt", kan het systeem plat leggen. De ontwerpeisen voor een coöperatief multitaskingprogramma kunnen bijzonder zwaar zijn voor bepaalde toepassingen en kunnen uitmonden in een onregelmatig of inefficiënt gebruik van de systeembronnen.
Om dit probleem aan te pakken, gingen de meeste tijdscharingsystemen preëmptieve multitasking toepassen, een techniek die al langer standaard was in grotere (multi-user-)besturingssystemen zoals UNIX en VMS. Een systeem dat is ontworpen met deze methode hoeft niet meer te vertrouwen op het vrijwillig vrijgeven van de processor, maar gebruikt hardware-interrupts om een draaiend programma te onderbreken waarna het besturingssysteem de controle over het systeem terugkrijgt. Op een later moment kan het besturingssysteem de controle weer teruggeven aan de taak die op precies dezelfde plek weer verdergaat als waar hij onderbroken werd. Taken hoeven dus niet expliciet tijd voor andere taken vrij te maken en programma's kunnen geschreven worden alsof ze continu toegang hebben tot de CPU. Op grotere systemen is deze aanpak onmisbaar om te voorkomen dat verschillende gebruikers elkaar in de weg zitten, maar op personal computers werd deze aanpak slechts langzaam geïntroduceerd, met name door op UNIX gebaseerde besturingssystemen zoals Minix en Linux.
Preëmptieve multitasking zorgt er dus voor dat een besturingssysteem makkelijker kan garanderen dat elke taak een deel van de processortijd toegewezen krijgt. Het maakt het ook mogelijk om snel te reageren op belangrijke externe gebeurtenissen, zoals binnenkomende data die wellicht direct verwerkt moeten worden door een taak.
Taken kunnen gegroepeerd worden in twee categorieën: taken die wachten op invoer of uitvoer (IO bound) en taken die de processor volledig gebruiken (CPU bound). In oudere systemen gebruikten taken polling en busy waiting terwijl ze wachtten op nieuwe data. Ze gebruikten daarbij de processor, zonder dat er nuttig werk werd verricht. Met de komst van interrupts en preëmptieve multitasking kunnen processen geblokkeerd worden zolang de gevraagde data niet beschikbaar is. Andere taken kunnen ondertussen wel gewoon gebruikmaken van de processor. Na aankomst van de data, maakt het besturingssysteem de taak weer actief zodat de data door het programma verwerkt kan worden.
Multitasking was oorspronkelijk bedoeld om verschillende gebruikers een computer te laten delen. Het werd echter al snel duidelijk dat multitasking nuttig was ongeacht het aantal gebruikers. Besturingssystemen van mainframes tot personal computers ondersteunen het tegenwoordig. Multitasking maakt het mogelijk voor een enkele gebruiker om verschillende applicaties naast elkaar te draaien of om taken op de "achtergrond" te draaien en toch de computer te kunnen gebruiken.
Het ontwerpen van een algemeen realtimecomputersysteem wordt ook mogelijk gemaakt door multitasking. Een aantal verschillende externe gebeurtenissen moet bestuurd worden door een systeem met een enkele processor. In dergelijke systemen kent de interruptafhandeling prioriteiten toe aan de taken om er zo voor te zorgen dat de belangrijkste taken de meeste processortijd toegewezen krijgen.
Multitasking is over de jaren heen behoorlijk verfijnd. Moderne besturingssystemen bevatten mechanismen voor het toekennen van prioriteiten aan taken en ondersteunen ook taken met threads. Threads zijn onafhankelijke subtaken die het geheugen delen met andere threads. Er wordt onderscheid gemaakt tussen multitasking en multithreading.
Nieuwe hardwaremogelijkheden (zoals SMP, NUMA, multiprocessing) introduceren zowel nieuwe complexiteiten als nieuwe mogelijkheden.
Voor verschillende taken die naast elkaar kunnen worden uitgevoerd kan men – afhankelijk van het beturingssysteem – de prioriteit aangeven. Bij meer ontwikkelde systemen als VMS en MVS kan de prioriteit van een taak tijdens de uitvoering veranderd worden; bij meer primitieve systemen kan deze prioriteit alleen bij het opstarten worden bepaald.
De scheduler van het besturingssysteem zou de taken als volgt kunnen inplannen:
Maar het volgende is ook mogelijk:
Omdat de programma's verschillende taken uitvoeren, hebben ze geen invloed op elkaar. Het wordt anders als een programma iets wil doen waar een ander programma al mee bezig is, bijvoorbeeld het schrijven naar een bestand. Als twee programma's naar hetzelfde bestand zouden schrijven, gaat een versie altijd verloren. Het is maar de vraag welke versie. Dit moet dus altijd worden voorkomen.
Programma's zijn in eerste instantie gemaakt alsof ze zonder te stoppen worden doorlopen. Dan kunnen er geen problemen optreden.
Voor beginnende programmeurs kan dit frustrerend zijn. Het volgende voorbeeld is een bekende beginnersfout omtrent multitasking:
De uitvoer zou zijn: Het programma lijkt 10 seconden niets te doen, daarna verschijnt een rood balletje. Het groene balletje lijkt niet getoond te worden.
Om dit probleem op te lossen moet het programma aangeven dat het even niets doet. Dit gebeurt met het commando ProcessMessages. De verbeterde code wordt nu:
Nu verschijnt het groene balletje, na 10 seconden wordt het balletje rood. Tijdens (dus direct na) het commando ProcessMessages wordt niet alleen het balletje getekend. Het programma wordt in de 'wacht' gezet, en er wordt gekeken of er nog andere programma's in de wacht staan. Het programma dat het langste in de wacht stond wordt verder uitgevoerd tot het commando ProcessMessages weer wordt tegengekomen.
Een nadeel, aan de hand van het voorgaande voorbeeld:
Hoe moet het dan? In plaats van Wacht 10 seconden zou je kunnen zeggen:
Resultaat: Het programma hangt gedurende 5 seconden. Het programma leeft even op, het scherm wordt ververst, en dan hangt het programma weer vijf seconden.