Delphiben a párhuzamosságot legegyszerűbben a TThread osztály felhasználásával tudjuk megvalósítani. Ez egy absztrakt osztály, ezért közvetlenül nem használhatjuk, azonban a belőle származtatott alosztályok képesek lesznek a párhuzamosságra.
Természetesen Delphiben is lehetőség van a Windowsban megszokott API hívásokon keresztül (pl.: CreateThread) megvalósítani a szálakat, azonban a TThread osztály használata sokkal kényelmesebb, és egy-két esettől eltekintve elegendő szolgáltatást nyújt párhuzamos programok írásához. Egyedül az osztott erőforrások használatánál felmerülő problémáknál fontos a Windows API hívások használata, ezek azonban (mint később látni fogjuk) jól kombinálhatók a TThread osztállyal.
A TThread osztály legfontosabb (virtuális) absztrakt művelete az Execute() metódus, melyet minden leszármazottban felül kell definiálni. Ez tartalmazza a szál fő kódját. Szálat a Create konstruktor meghívásával hozhatunk létre, melynek egy Boolean paramétere van (CreateSuspended), mellyel azt adjuk meg, hogy a szál felfüggesztődjön (true), vagy a létrehozás után azonnal elinduljon (false).
Ezek alapján egy rövid példa:
Ezt a TMyThread osztályt példányosítva elindul annyi szál, amennyit csak példányosítunk belőle. Egy ajánlás, hogy egyprocesszoros gépen nem használjunk 16 szálnál többet, mert nagyon rámehet a sebesség rovására.
Az egyes szálaknak külön-külön prioritás adható, és ilyen mértékben kapnak időt a futásra. A prioritás értéket a szál Priority attribútumában kell beállítani: tpIdle, tpLowest, tpLower, tpNormal, tpHigher, tpHighest, tpTimeCritical.
Lehetőségünk van egy szálat elaltatni (Suspend), felébreszteni (Resume), illetve ugyanezt tehetjük a Suspended (Boolean típusú) property állításával. Lehetőségünk van továbbá arra is, hogy egy másik szálat bevárjunk, ezt úgy tehetjük meg, hogy az illető szál WaitFor metódusát meghívjuk. (Ennél a hívásnál persze vigyáznunk kell, nehogy a programunk holtpontra jusson.) Ezek alapján egy példa, amelyben példányosítunk egy szálat, majd megvárjuk, míg befejeződik a végrehajtása.
Minden szálnak van egy Terminated logikai tagja, amellyel jelezhetjük a szándékunkat a terminálásra. Nem kényszeríti ki a leállítást, viszont hasznos lehet olyan szálnál, amely ismétlődő feladatot hajt végre végtelen ciklusban, ilyenkor a Terminated jelentheti a megállási feltételt. Meg lehet adni a FreeOnTerminated értékkel, hogy ha lefutott, akkor számolja fel magát a szál. A ReturnValue integer a visszatérő értéke a szálnak (a WaitFor az ebben tárolt értéket adja vissza).
A TThread osztálynak létezik egy Synchronize metódusa, amelynek segítségével elkerülhetjük a VCL komponensek egyidejű használatából adódó konfliktusokat. Ennek a paramétere egy paraméterekkel nem rendelkező metódus (TThreadMethod).
Szinkronizációra még lehetőség nyílik úgy is, hogy néhány VCL objektumnak van Lock, Unlock metóduspárja. Pl. a TCanvas esetében:
Kritikus szakasznak a forráskód azon részeit nevezzük, melyeket két szál egyidejűleg nem futtathat. Ezek használatával biztosíthatjuk, hogy a program ezen részei egymástól függetlenül hajtódjanak végre. Kritikus szakaszokat csak egy alkalmazáson belül használhatunk.
A Delphi 3-ban került bevezetésre a VCL részeként a TCriticalSection osztály (a SyncObjs egységben). Ennek segítségével a kritikus szakaszok használata a következő:
Mutexek segítségével különböző erőforrásokhoz való hozzáférést szabályozhatjuk. Az erőforrás használata előtt a mutexet le kell foglalni, majd az erőforrás használata után fel kell engedni azt. A mutex foglalt állapotában egy másik szál nem tudja lefoglalni azt. Meg kell várnia, míg az előző szál felengedi azt. A mutex (a kritikus szakaszokkal ellentétben) megosztható különböző alkalmazások között a neve segítségével.
Példa mutex használatára:
A szemafor a mutexhez hasonló, azonban egyszerre nem csak egy szálnak engedi a hozzáférést. Megadhatjuk például, hogy egy adott erőforráshoz egy időben maximálisan hányan férhetnek hozzá. A mutex lényegében egy olyan szemafor, melynek maximális szálszáma 1.
A szinkronizációs esemény egy olyan objektum, amelyet egy szál kiválthat, így jelezve egy másik szálnak, hogy folytathatja a tevékenységét.