SLIDE 1
Mul$-‑Object ¡Synchroniza$on ¡
SLIDE 2 Mul$-‑Object ¡Programs ¡
- What ¡happens ¡when ¡we ¡try ¡to ¡synchronize ¡
across ¡mul$ple ¡objects ¡in ¡a ¡large ¡program? ¡
– Each ¡object ¡with ¡its ¡own ¡lock, ¡condi$on ¡variables ¡ – Is ¡locking ¡modular? ¡
- Performance ¡
- Seman$cs/correctness ¡
- Deadlock ¡
- Elimina$ng ¡locks ¡
SLIDE 3 Synchroniza$on ¡Performance ¡ ¡
- Speedup ¡= ¡Time ¡on ¡one ¡CPU/Time ¡on ¡N ¡CPUs ¡
- A ¡program ¡with ¡lots ¡of ¡concurrent ¡threads ¡can ¡
have ¡poor ¡speedup, ¡because: ¡
– Lock ¡conten$on: ¡only ¡one ¡thread ¡at ¡a ¡$me ¡holding ¡ a ¡given ¡lock ¡ – Shared ¡data ¡protected ¡by ¡a ¡lock ¡may ¡ping ¡back ¡ and ¡forth ¡between ¡cores ¡ – False ¡sharing: ¡communica$on ¡between ¡cores ¡even ¡ for ¡data ¡that ¡is ¡not ¡shared ¡
SLIDE 4 Ques$on ¡
- Suppose ¡a ¡cri$cal ¡sec$on ¡is ¡5% ¡of ¡the ¡total ¡
work ¡per ¡request ¡(on ¡a ¡single ¡CPU) ¡
- What ¡is ¡maximum ¡possible ¡speedup ¡from ¡
running ¡each ¡request ¡in ¡its ¡own ¡thread? ¡
- Suppose ¡CPU ¡is ¡5x ¡slower ¡when ¡execu$ng ¡in ¡
cri$cal ¡sec$on ¡due ¡to ¡cache ¡effects ¡
- What ¡is ¡maximum ¡possible ¡speedup? ¡
SLIDE 5 A ¡Simple ¡Test ¡of ¡Cache ¡Behavior ¡
- An ¡array ¡of ¡locks, ¡each ¡protects ¡a ¡counter ¡
– Cri$cal ¡sec$on: ¡increment ¡counter ¡ – Mul$ple ¡cores ¡
- Test ¡1: ¡one ¡thread ¡loops ¡over ¡array ¡
- Test ¡2: ¡two ¡threads ¡loop ¡over ¡different ¡arrays ¡
- Test ¡3: ¡two ¡threads ¡loop ¡over ¡single ¡array ¡
- Test ¡4: ¡two ¡threads ¡loop ¡over ¡alternate ¡
elements ¡in ¡single ¡array ¡
SLIDE 6
Results ¡
One ¡thread, ¡one ¡array ¡ ¡ ¡51 ¡cycles ¡ Two ¡threads, ¡two ¡arrays ¡ ¡ ¡52 ¡ ¡ Two ¡threads, ¡one ¡array ¡ 197 ¡ Two ¡threads, ¡odd/even ¡ 127 ¡
SLIDE 7 Reducing ¡Lock ¡Conten$on ¡
- Fine-‑grained ¡locking ¡
– Par$$on ¡object ¡into ¡subsets, ¡each ¡protected ¡by ¡its ¡own ¡ lock ¡ – Example: ¡hash ¡table ¡buckets ¡
- Per-‑processor ¡data ¡structures ¡
– Par$$on ¡object ¡so ¡that ¡most/all ¡accesses ¡are ¡made ¡by ¡
– Example: ¡per-‑processor ¡heap ¡
– Check ¡out ¡item, ¡modify, ¡check ¡back ¡in ¡
– Divide ¡and ¡conquer ¡
SLIDE 8 What ¡If ¡Locks ¡are ¡S$ll ¡Busy? ¡
– Op$mize ¡lock ¡implementa$on ¡for ¡when ¡lock ¡is ¡ contended ¡
- RCU ¡(read-‑copy-‑update) ¡
– Efficient ¡readers/writers ¡lock ¡used ¡in ¡Linux ¡kernel ¡ – Readers ¡proceed ¡without ¡first ¡acquiring ¡lock ¡ – Writer ¡ensures ¡that ¡readers ¡are ¡done ¡
SLIDE 9 Read-‑Copy-‑Update ¡
– Writer ¡computes ¡new ¡version ¡of ¡data ¡structure ¡ ¡ – Publishes ¡new ¡version ¡with ¡a ¡single ¡atomic ¡instruc$on ¡
- Mul$ple ¡concurrent ¡versions ¡
– Readers ¡may ¡see ¡old ¡or ¡new ¡version ¡
- Integra$on ¡with ¡thread ¡scheduler ¡
– Guarantee ¡all ¡readers ¡complete ¡within ¡grace ¡period, ¡ and ¡then ¡garbage ¡collect ¡old ¡version ¡ – OK ¡if ¡write ¡is ¡slow ¡
SLIDE 10 Read-‑Copy-‑Update ¡
Read (Old) Read (Old or New) Read (New) Read (New) Read (New) Read (Old) Write (New) Delete (Old) Read (Old or New)
Update is Published Grace Period Ends Grace Period Time
SLIDE 11 Read-‑Copy-‑Update ¡Implementa$on ¡
- Readers ¡disable ¡interrupts ¡on ¡entry ¡
– Guarantees ¡they ¡complete ¡cri$cal ¡sec$on ¡in ¡a ¡$mely ¡ fashion ¡ – No ¡read ¡or ¡write ¡lock ¡
– Acquire ¡write ¡lock ¡ – Compute ¡new ¡data ¡structure ¡ – Publish ¡new ¡version ¡with ¡atomic ¡instruc$on ¡ – Release ¡write ¡lock ¡ – Wait ¡for ¡$me ¡slice ¡on ¡each ¡CPU ¡ – OK ¡to ¡garbage ¡collect ¡
SLIDE 12 Deadlock ¡Defini$on ¡
- Resource: ¡any ¡(passive) ¡thing ¡needed ¡by ¡a ¡
thread ¡to ¡do ¡its ¡job ¡(CPU, ¡disk ¡space, ¡memory, ¡ lock) ¡
– Preemptable: ¡can ¡be ¡taken ¡away ¡by ¡OS ¡ – Non-‑preemptable: ¡must ¡leave ¡with ¡thread ¡
- Starva$on: ¡thread ¡waits ¡indefinitely ¡
- Deadlock: ¡circular ¡wai$ng ¡for ¡resources ¡
– Deadlock ¡=> ¡starva$on, ¡but ¡not ¡vice ¡versa ¡
SLIDE 13
Example: ¡two ¡locks ¡
Thread ¡A ¡ lock1.acquire(); ¡ lock2.acquire(); ¡ lock2.release(); ¡ lock1.release(); ¡ Thread ¡B ¡ lock2.acquire(); ¡ lock1.acquire(); ¡ lock1.release(); ¡ lock2.release(); ¡
SLIDE 14
Bidirec$onal ¡Bounded ¡Buffer ¡
Thread ¡A ¡ buffer1.put(data); ¡ buffer1.put(data); ¡ buffer2.get(); ¡ buffer2.get(); ¡ Thread ¡B ¡ buffer2.put(data); ¡ buffer2.put(data); ¡ buffer1.get(); ¡ buffer1.get(); ¡
SLIDE 15
Two ¡locks ¡and ¡a ¡condi$on ¡variable ¡
Thread ¡A ¡ lock1.acquire(); ¡ … ¡ lock2.acquire(); ¡ while ¡(need ¡to ¡wait) ¡ ¡ ¡ ¡condi$on.wait(lock2); ¡ lock2.release(); ¡ … ¡ lock1.release(); ¡ Thread ¡B ¡ lock1.acquire(); ¡ … ¡ lock2.acquire(); ¡ …. ¡ condi$on.signal(lock2); ¡ lock2.release(); ¡ … ¡ lock1.release(); ¡
SLIDE 16
Yet ¡another ¡Example ¡
SLIDE 17
Dining ¡Lawyers ¡
Each ¡lawyer ¡needs ¡two ¡chops$cks ¡to ¡eat. ¡ ¡ Each ¡grabs ¡chops$ck ¡on ¡the ¡right ¡first. ¡
SLIDE 18 Necessary ¡Condi$ons ¡for ¡Deadlock ¡
- Limited ¡access ¡to ¡resources ¡
– If ¡infinite ¡resources, ¡no ¡deadlock! ¡
– If ¡resources ¡are ¡virtual, ¡can ¡break ¡deadlock ¡
- Mul$ple ¡independent ¡requests ¡
– “wait ¡while ¡holding” ¡
- Circular ¡chain ¡of ¡requests ¡
SLIDE 19 Ques$on ¡
- How ¡does ¡Dining ¡Lawyers ¡meet ¡the ¡necessary ¡
condi$ons ¡for ¡deadlock? ¡
– Limited ¡access ¡to ¡resources ¡ – No ¡preemp$on ¡ – Mul$ple ¡independent ¡requests ¡(wait ¡while ¡holding) ¡ – Circular ¡chain ¡of ¡requests ¡
- How ¡can ¡we ¡modify ¡system ¡to ¡prevent ¡
deadlock? ¡
SLIDE 20 Example ¡
Thread ¡1 ¡
- 1. Acquire ¡A ¡
- 2. ¡ ¡
- 3. Acquire ¡C ¡
- 4. ¡ ¡
- 5. Wait ¡for ¡B ¡
Thread ¡2 ¡
- 1. ¡ ¡
- 2. Acquire ¡B ¡
- 3. ¡ ¡
- 4. Wait ¡for ¡A ¡
How ¡could ¡we ¡have ¡avoided ¡deadlock? ¡
SLIDE 21 Preven$ng ¡Deadlock ¡
- Exploit ¡or ¡limit ¡program ¡behavior ¡
– Limit ¡program ¡from ¡doing ¡anything ¡that ¡might ¡ lead ¡to ¡deadlock ¡
– If ¡we ¡know ¡what ¡program ¡will ¡do, ¡we ¡can ¡tell ¡if ¡ gran$ng ¡a ¡resource ¡might ¡lead ¡to ¡deadlock ¡
– If ¡we ¡can ¡rollback ¡a ¡thread, ¡we ¡can ¡fix ¡a ¡deadlock ¡
SLIDE 22 Exploit ¡or ¡Limit ¡Behavior ¡
- Provide ¡enough ¡resources ¡
– How ¡many ¡chops$cks ¡are ¡enough? ¡
- Eliminate ¡wait ¡while ¡holding ¡
– Release ¡lock ¡when ¡calling ¡out ¡of ¡module ¡ – Telephone ¡circuit ¡setup ¡
- Eliminate ¡circular ¡wai$ng ¡
– Lock ¡ordering: ¡always ¡acquire ¡locks ¡in ¡a ¡fixed ¡order ¡ – Example: ¡move ¡file ¡from ¡one ¡directory ¡to ¡another ¡
SLIDE 23 Predict ¡the ¡Future ¡
– State ¡maximum ¡resource ¡needs ¡in ¡advance ¡ – Allocate ¡resources ¡dynamically ¡when ¡resource ¡is ¡ needed ¡-‑-‑ ¡wait ¡if ¡gran$ng ¡request ¡would ¡lead ¡to ¡ deadlock ¡ – Request ¡can ¡be ¡granted ¡if ¡some ¡sequen$al ¡
- rdering ¡of ¡threads ¡is ¡deadlock ¡free ¡
SLIDE 24
Possible ¡System ¡States ¡
Safe Unsafe Deadlock
SLIDE 25 Defini$ons ¡
– For ¡any ¡possible ¡sequence ¡of ¡future ¡resource ¡ requests, ¡it ¡is ¡possible ¡to ¡eventually ¡grant ¡all ¡requests ¡ – May ¡require ¡wai$ng ¡even ¡when ¡resources ¡are ¡ available! ¡
– Some ¡sequence ¡of ¡resource ¡requests ¡can ¡result ¡in ¡ deadlock ¡ ¡
– All ¡possible ¡computa$ons ¡lead ¡to ¡deadlock ¡
SLIDE 26 Banker’s ¡Algorithm ¡
- Grant ¡request ¡iff ¡result ¡is ¡a ¡safe ¡state ¡
- Sum ¡of ¡maximum ¡resource ¡needs ¡of ¡current ¡
threads ¡can ¡be ¡greater ¡than ¡the ¡total ¡resources ¡
– Provided ¡there ¡is ¡some ¡way ¡for ¡all ¡the ¡threads ¡to ¡finish ¡ without ¡genng ¡into ¡deadlock ¡
– total ¡available ¡resources ¡-‑ ¡# ¡allocated ¡>= ¡max ¡ remaining ¡that ¡might ¡be ¡needed ¡by ¡this ¡thread ¡in ¡
– Guarantees ¡this ¡thread ¡can ¡finish ¡
SLIDE 27 Example: ¡Banker’s ¡Algorithm ¡
- n ¡chops$cks ¡in ¡middle ¡of ¡table ¡ ¡
- n ¡lawyers, ¡each ¡can ¡take ¡one ¡chops$ck ¡at ¡a ¡
$me ¡
- When ¡is ¡it ¡ok ¡for ¡lawyer ¡to ¡take ¡a ¡chops$ck? ¡
- What ¡if ¡each ¡lawyer ¡needs ¡k ¡chops$cks? ¡
SLIDE 28 Detect ¡and ¡Repair ¡
– Scan ¡wait ¡for ¡graph ¡ – Detect ¡cycles ¡ – Fix ¡cycles ¡
- Proceed ¡without ¡the ¡resource ¡
– Requires ¡robust ¡excep$on ¡handling ¡code ¡
– Transac$on: ¡all ¡opera$ons ¡are ¡provisional ¡un$l ¡have ¡ all ¡required ¡resources ¡to ¡complete ¡opera$on ¡
SLIDE 29 Detec$ng ¡Deadlock ¡
Waiting for Owned by Owned by Waiting for Resource X Resource Y Thread 1 Thread 0 Owned by Waiting for Owned by Waiting for Owned by Resource X Resource Y Thread 1 Thread 2 Thread 0
SLIDE 30 Non-‑Blocking ¡Synchroniza$on ¡
- Compare ¡and ¡swap ¡atomic ¡instruc$on ¡
– Create ¡copy ¡of ¡data ¡structure ¡ – Modify ¡copy ¡ – Swap ¡in ¡new ¡version ¡iff ¡no ¡one ¡else ¡has ¡ – Restart ¡if ¡pointer ¡has ¡changed ¡
SLIDE 31
Lock-‑Free ¡Bounded ¡Buffer ¡
tryget() ¡{ ¡ ¡ ¡ ¡do ¡{ ¡ ¡ ¡ ¡ ¡ ¡copy ¡= ¡ConsistentCopy(p); ¡ ¡ ¡ ¡ ¡ ¡if ¡(copy-‑>front ¡== ¡copy-‑>tail) ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡return ¡NULL; ¡ ¡ ¡ ¡ ¡ ¡else ¡{ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡item ¡= ¡copy-‑>buf[copy-‑>front ¡% ¡MAX]; ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡copy-‑>front++; ¡ ¡ ¡ ¡ ¡ ¡ ¡} ¡ ¡ ¡ ¡ ¡while ¡((compare&swap(copy, ¡p) ¡!= ¡p); ¡ ¡ ¡ ¡ ¡return ¡item ¡ } ¡