# Gelijktijdigheid (informatica)

In de informatica is gelijktijdigheid (Engels: concurrency) het zich in dezelfde tijdsperiode afspelen van verschillende processen of activiteiten, die dan gelijktijdig worden genoemd. Deze term wordt met name gebruikt als de processen in kwestie geacht worden om samen te werken, bijvoorbeeld door het uitwisselen van informatie of het delen van gemeenschappelijke voorzieningen, en zo de algehele voortgang te bevorderen.
Tegengesteld hieraan is een sequentieel proces, waarin alle stappen strikt na elkaar worden uitgevoerd, en dus van gelijktijdigheid geen sprake is.
Het probleemloos laten samenwerken van gelijktijdige processen blijkt tal van ingewikkelde moeilijkheden met zich mee te brengen die zich bij sequentiële processen helemaal niet voordoen.
In de werkelijkheid zijn gelijktijdige processen heel gewoon: zo kunnen bijvoorbeeld de activiteiten van verschillende werknemers van hetzelfde bedrijf als zodanig worden beschouwd. Bij het programmeren van computers daarentegen werd er traditioneel meestal van uitgegaan dat er zich slechts een proces tegelijk kan afspelen, namelijk het strikt sequentieel uitvoeren van een reeks instructies door de processor. Dit gaat niet langer op voor moderne computers, die meerdere processoren hebben met elk meerdere rekenkernen, en waarin zelfs een enkele rekenkern reeksen instructies niet langer strikt sequentieel uitvoert, maar geparallelliseerd. Bovendien worden softwaresystemen veel vaker dan vroeger gedistribueerd opgezet, waarbij meer dan een computer samenwerkt om het uiteindelijke resultaat te bereiken.
Verscheidene wiskundige modellen zijn ontwikkeld voor de beschrijving van gelijktijdige processen, waaronder petri-netten, procescalculi, de parallelle RAM-machine, het actormodel en coördinatietalen zoals Linda en Reo.

## Geschiedenis

In de zestiger jaren gingen grotere computers multiprocessing ondersteunen; hierdoor werden informatici zoals Edsger Dijkstra en Tony Hoare zich bewust van de specifieke problemen die dat met zich meebracht. Dijkstra was mogelijk de eerste die zich realiseerde dat zulke problemen wiskundig gespecificeerd en opgelost zouden kunnen worden. Een voorbeeld van zo'n formulering is het filosofenprobleem, oorspronkelijk gesteld door Dijkstra en door Hoare in een meer aansprekende vorm gegoten. Uit dit begin ontwikkelde zich een apart specialisme in de informatica, de gelijktijdigheidstheorie, met bijdragen zoals de theorie van Leslie Lamport over het correct rekenen met gedeeld geheugen, de procescalculi uit de jaren 80 en 90 van Robin Milner en anderen, de ontwikkeling van petrinetten, Kahn-netwerken en allerlei andere formalismen voor gelijktijdige berekening, tot aan de recente introductie van veilige mechanismen voor asynchrone procesuitvoering in populaire programmeertalen zoals C# en JavaScript.
Lamport (2015) stelt: "Ook al werd de gelijktijdige uitvoering van programma's al langer bestudeerd, deze werd pas onderdeel van de theoretische informatica door het baanbrekende artikel uit 1965 waarin Edsger Dijkstra het probleem van de wederzijdse uitsluiting introduceerde. ... In de daaropvolgende decennia is de belangstelling voor gelijktijdigheid enorm toegenomen, met name in gedistribueerde systemen. Kijken we naar de oorsprong van dit specialisme, dan valt een ding op: de fundamentele rol van Edsger Dijkstra."

## Moeilijkheden

Omdat gelijktijdige rekenprocessen tijdens hun uitvoering interacties kunnen hebben, kan het aantal mogelijke uitvoeringsvolgorden in het systeem extreem groot zijn, en de resulterende uitkomst onderbepaald. Een mogelijke bron hiervan is het gedeelde gebruik van voorzieningen zoals opslagmedia, wat kan leiden tot problemen zoals impasses en uithongering.
Het ontwerp van systemen met gelijktijdige processen brengt met zich mee dat betrouwbare technieken moeten worden gevonden voor het coördineren van hun uitvoering, voor de gegevensuitwisseling, het geheugenbeheer en de uitvoeringsplanning om de reactietijd te minimaliseren en de doorvoer te maximaliseren.

## Theorie

De gelijktijdigheidstheorie is een actief onderzoeksgebied in de theoretische informatica sinds de vroege jaren zestig. Een van de eerste voorstellen was het baanbrekende werk van Carl Adam Petri over petri-netten. In dezelfde tijd werd de programmeertaal Simula ontwikkeld, die oorspronkelijk bedoeld was als specificatie- en simulatietaal voor systemen bestaande uit communicerende gelijktijdige processen. Sindsdien is een grote verscheidenheid aan formalismen ontwikkeld voor het modelleren en redeneren over gelijktijdigheid, en een grote hoeveelheid programmeerconstructies om met gelijktijdigheid om te gaan in de dagelijkse programmeerpraktijk.

### Modellen

Er zijn tal van formalismen ontwikkeld voor het modelleren en begrijpen van gelijktijdige systemen, zoals:
* De parallelle RAM-machine
* Het actor-model
* Computationele overbruggingsmodellen zoals het bulksynchrone parallelle (BSP) model
* Petri-netten
* Procescalculi, zoals
** Calculus of communicating systems (CCS)
** Communicerende sequentiële processen (CSP)
** de π-calculus
** de join-calculus
* Coördinatietalen gebaseerd op tupelruimtes, bijv. Linda
* Simple Concurrent Object-Oriented Programming (SCOOP)
* De coördinatietaal Reo
Sommige van deze gelijktijdigheidsmodellen zijn primair bedoeld om redenering en specificatie te ondersteunen, terwijl andere modellen gedurende de hele ontwikkelingscyclus kunnen worden gebruikt, inclusief ontwerp, implementatie, correctheidsbewijs, testen en simulatie. Sommige modellen zijn gebaseerd op berichtuitwisseling, andere gebruiken andere communicatiemechanismen.
De verveelvuldiging van al deze gelijktijdigheidsmodellen heeft sommige onderzoekers ertoe gebracht om manieren te ontwikkelen om deze verschillende theoretische modellen te verenigen. Lee en Sangiovanni-Vincentelli hebben bijvoorbeeld aangetoond dat een zogenaamd "geëtiketteerd-signaal"-model als gemeenschappelijk raamwerk kan dienen voor het definiëren van de denotationele semantiek van tal van verschillende gelijktijdigheidsmodellen, terwijl Nielsen, Sassone en Winskel hebben aangetoond dat een vergelijkbaar uniform raamwerk kan worden verschaft op basis van categorietheorie.

### Logica's

Verscheidene soorten temporele logica kunnen worden gebruikt om te helpen redeneren over gelijktijdige systemen. Sommige van deze logica's, zoals de lineaire temporele logica en de berekeningsboomlogica, maken het mogelijk om beweringen te doen over de opeenvolgingen van toestanden waarin een gelijktijdig systeem zich kan bevinden. Andere logica's, zoals de actieberekeningsboomlogica, de Hennessy-Milner-logica en de temporele logica van Lamport, doen juist beweringen aangaande de mogelijke opeenvolgingen van acties (toestandsveranderingen). De belangrijkste toepassing van deze logica's is het schrijven van specificaties voor systemen waarin gelijktijdigheid voorkomt.

## Praktijk

Gelijktijdige programmering (concurrent programming) is het gebruik van programmeerconstructies en algoritmen die specifiek zijn ontworpen voor de omgang met gelijktijdigheid. Het is een meer algemeen begrip dan parallel programmeren, omdat het arbitraire en dynamische patronen van communicatie en interactie kan omvatten, terwijl parallelle systemen in het algemeen een vooraf gedefinieerd en goed gestructureerd communicatiepatroon hebben. De oogmerken van gelijktijdige programmering zijn correctheid, prestaties en robuustheid. Gelijktijdigheid ondersteunende systemen zoals besturingssystemen en databasebeheersystemen zijn over het algemeen ontworpen om voor onbepaalde tijd te blijven draaien, en ondersteunen daarom vaak automatisch herstel van storingen en het opvangen van onverwachte beëindiging van processen (zie concurrency-controle). Sommige gelijktijdige systemen implementeren een vorm van transparante gelijktijdigheid, waarbij gelijktijdige rekenprocessen kunnen wedijveren om dezelfde gedeelde voorziening zonder dat de complexiteit hiervan getoond wordt aan de applicatieprogrammeur.