cps 310 threads and concurrency topics
play

CPS 310 Threads and Concurrency: Topics Jeff Chase Duke - PowerPoint PPT Presentation

D D u k e S y s t t e m s CPS 310 Threads and Concurrency: Topics Jeff Chase Duke University h>p://www.cs.duke.edu/~chase/cps310 Terminology and syntax The abstractions for


  1. D D u k e S y s t t e m s CPS ¡310 ¡ Threads ¡and ¡Concurrency: ¡Topics ¡ Jeff ¡Chase ¡ Duke ¡University ¡ ¡ h>p://www.cs.duke.edu/~chase/cps310 ¡

  2. Terminology and syntax • The abstractions for concurrency control in this class are now sort-of universal at the OS/API level. • Monitors (mutex+CV) with Mesa semantics appear in: – Java (e.g., on Android) and JVM languages (e.g., Scala) – POSIX threads or Pthreads (used on Linux and MacOS/iOS) – Windows, C#/.NET, and other Microsoft systems • Terminology and APIs vary a bit. – mutex == lock == Java “synchronized” – monitor == mutex + condition variable (CV) – signal() == notify(), broadcast() == notifyAll() • The slides use interchangeable terms interchangeably.

  3. Example: the soda/HFCS machine Soda ¡drinker ¡ (consumer) ¡ Delivery ¡person ¡ (producer) ¡ Vending ¡machine ¡ (buffer) ¡

  4. Producer-consumer code consumer () { producer () { take a soda from machine add one soda to machine } }

  5. Solving producer-consumer 1. What are the variables/shared state? ê Soda machine buffer ê Number of sodas in machine ( ≤ MaxSodas) 2. Locks? ê 1 to protect all shared state (sodaLock) 3. Mutual exclusion? ê Only one thread can manipulate machine at a time 4. Ordering constraints? ê Consumer must wait if machine is empty (CV hasSoda) ê Producer must wait if machine is full (CV hasRoom)

  6. Producer-consumer code consumer () { producer () { lock lock take a soda from machine add one soda to machine unlock unlock } }

  7. Producer-consumer code consumer () { producer () { lock lock wait if empty wait if full take a soda from machine add one soda to machine notify (not full) notify (not empty) unlock unlock } }

  8. Producer-consumer code consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasSoda) wait (sodaLock, hasRoom) Mx ¡ CV1 ¡ Mx ¡ CV2 ¡ } } take a soda from machine add one soda to machine signal (hasRoom) signal (hasSoda) CV1 ¡ CV2 ¡ unlock (sodaLock) unlock (sodaLock) } }

  9. Producer-consumer code synchronized consumer () { synchronized producer () { while(numSodas==maxSodas) { while (numSodas == 0) { wait () o.wait () } } put a soda from machine take a soda from machine notify(); notify(); } }

  10. Producer-consumer code consumer () { synchronized(o) { while (numSodas == 0) { o.wait () } take a soda o.notify(); } }

  11. Producer-consumer code consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasSoda) wait (sodaLock, hasRoom) } } take a soda from machine fill machine with soda signal(hasRoom) broadcast(hasSoda) unlock (sodaLock) unlock (sodaLock) } } The ¡signal ¡should ¡be ¡a ¡broadcast ¡if ¡the ¡producer ¡can ¡produce ¡ more ¡than ¡one ¡resource, ¡and ¡there ¡are ¡mulOple ¡consumers. ¡ ¡ lpcox slide edited by chase

  12. Variations: looping producer producer () { ê Producer lock (sodaLock) while (1) { ê Infinite loop ok? while(numSodas==MaxSodas){ wait (sodaLock, hasRoom) ê Why/why not? } ê Release lock in add soda to machine wait call signal (hasSoda) } unlock (sodaLock) }

  13. Variations: resting producer producer () { ê Producer lock (sodaLock) while (1) { ê Sleep ok? sleep (1 hour) while(numSodas==MaxSodas){ ê Why/why not? wait (sodaLock, hasRoom) } ê Shouldn ’ t hold add soda to machine locks during a slow operation signal (hasSoda) } unlock (sodaLock) }

  14. Variations: one CV? consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasRorS) wait (sodaLock,hasRorS) Mx ¡ CV ¡ Mx ¡ CV ¡ } } take a soda from machine add one soda to machine signal (hasRorS) signal(hasRorS) CV ¡ CV ¡ unlock (sodaLock) unlock (sodaLock) } } Two ¡producers, ¡two ¡consumers: ¡who ¡consumes ¡a ¡signal? ¡ ¡ ProducerA ¡and ¡ConsumerB ¡wait ¡while ¡ConsumerC ¡signals? ¡

  15. Variations: one CV? consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasRorS) wait (sodaLock,hasRorS) } } take a soda from machine add one soda to machine signal (hasRorS) signal (hasRorS) unlock (sodaLock) unlock (sodaLock) } } Is ¡it ¡possible ¡to ¡have ¡a ¡producer ¡and ¡consumer ¡both ¡waiOng? ¡ ¡ ¡max=1, ¡cA ¡and ¡cB ¡wait, ¡pC ¡adds/signals, ¡pD ¡waits, ¡cA ¡wakes ¡

  16. Variations: one CV? consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasRorS) wait (sodaLock,hasRorS) } } take a soda from machine add one soda to machine signal (hasRorS) signal (hasRorS) unlock (sodaLock) unlock (sodaLock) } } How ¡can ¡we ¡make ¡the ¡one ¡CV ¡soluOon ¡work? ¡

  17. Variations: one CV? consumer () { producer () { lock (sodaLock) lock (sodaLock) while (numSodas == 0) { while(numSodas==MaxSodas){ wait (sodaLock,hasRorS) wait (sodaLock,hasRorS) } } take a soda from machine add one soda to machine broadcast (hasRorS) broadcast (hasRorS) unlock (sodaLock) unlock (sodaLock) } } Use ¡broadcast ¡instead ¡of ¡signal: ¡safe ¡but ¡slow. ¡

  18. Broadcast vs signal ê Can I always use broadcast instead of signal? ê Yes, assuming threads recheck condition ê And they should: “ loop before you leap ” ! ê Mesa semantics requires it anyway: another thread could get to the lock before wait returns. ê Why might I use signal instead? ê Efficiency (spurious wakeups) ê May wakeup threads for no good reason ê “ Signal is just a performance hint ” . lpcox slide edited by chase

  19. Locking a critical section The threads may run the critical section in either order, but the schedule can never enter the grey region where both threads mx->Acquire(); load execute the section at the same time. x = x + 1; add store mx->Release(); þ þ R x=x+1 mx->Acquire(); load A x = x + 1; add store mx->Release(); x=x+1 A R Holding a shared mutex prevents competing threads from entering a critical section protected by the shared mutex (monitor). At most one thread runs in the critical section at a time.

  20. Locking a critical section load add 3. store þ þ mx->Acquire(); load load add x = x + 1; add store store mx->Release(); load add þ þ 4. store synchronized mx->Acquire(); load serialized load x = x + 1; add atomic store add mx->Release(); store Holding a shared mutex prevents competing threads from entering a critical section. If the critical section code acquires the mutex, then its execution is serialized: only one thread runs it at a time.

  21. How about this? load A x = x + 1; add store mx->Acquire(); load x = x + 1; B add store mx->Release();

  22. How about this? load A x = x + 1; add store The locking discipline is not followed: purple fails to acquire the lock mx. mx->Acquire(); load Or rather: purple accesses the variable x = x + 1; B add store x through another program section A mx->Release(); that is mutually critical with B , but does not acquire the mutex. A locking scheme is a convention that the entire program must follow.

  23. How about this? lock->Acquire(); load add x = x + 1; A store lock->Release(); mx->Acquire(); load x = x + 1; B add store mx->Release();

  24. How about this? lock->Acquire(); load add x = x + 1; A store lock->Release(); This guy is not acquiring the right lock. Or whatever. They’re not using the mx->Acquire(); load same lock, and that’s what matters. x = x + 1; B add store mx->Release(); A locking scheme is a convention that the entire program must follow.

  25. Ucontext library routines • The system can use ucontext routines to: – “Freeze” at a point in time of the execution – Restart execution from a frozen moment in time – Execution continues where it left off … if the memory state is right. • The system can implement multiple independent threads of execution within the same address space. – Create a context for a new thread with makecontext : when switched in it will call a specified procedure with specified arg. – Modify saved contexts at will. – Context switch with swapcontext : transfer a core from one thread to another

  26. Messing with the context #include <ucontext.h> ucontext Standard C library routines to: int count = 0; ucontext_t context; Save current register context to a block of memory ( getcontext from core) int main() { Load /restore current register context int i = 0; from a block of memory ( setcontext ) getcontext (&context); Also: makecontext , swapcontext count += 1; i += 1; Details of the saved context (ucontext_t sleep(2); structure) are machine-dependent. printf(” … ", count, i); setcontext (&context); }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend