230 likes | 398 Views
CSE 451. Section 1/27/2000. Agenda. Homework Questions Project Questions Synchronization Examples. Homework Questions. 4.4: need to consider both user & kernel threads Need to balance protection vs. performance (e.g. web server)
E N D
CSE 451 Section 1/27/2000
Agenda • Homework Questions • Project Questions • Synchronization Examples
Homework Questions • 4.4: need to consider both user & kernel threads • Need to balance protection vs. performance (e.g. web server) • 4.5: When creating a process, need to consider other per-process resources • open file table, heap, page table • 4.6: need to be clearer about how an address space is switched • Pointer to current address space changed
Project Questions • Assignment 0: many people didn’t list: • When interrupts were enabled / disabled • When ChildFunction is called • When a thread finishes • Any questions?
Synchronization Types • Semaphore • Mutex • Monitor • Condition variables
Synchronization Examples • Linked List • Worker Threads • Reference Counting
Linked List • Have a basic list: Struct list_element { Struct list_element * Next, Int Data; } • How do you synchronize? • How many locks? • When do you lock?
Linked List (2) • Protect access to list itself: • Use mutex, if reading and writing both common • Use reader/writer lock of reading more common • Protect access to the data of the list • Use a mutex per item? • Use a mutex for all the data? • Signaling events for the list • List empty? • List full?
Deadlock • What if have mutex per list item: • Thread A locks object 1 • Thread B locks object 2 • Thread A blocks trying to lock object 2 • Thread B blocks trying to lock object 1 • What to do?
Deadlock Prevention • When waiting, see if other thread is waiting for any locks you own. • Lock all objects in order, so both threads lock Object 1 then Object 2
Reference Counting • Pool of data structures used by several threads • Periodically, new ones are added, existing ones deleted • May be in use when deleted
Reference Counting (2) • Have a linked list of objects • Have a reference count per object • One count for being on list • One count for being in use • When in use by thread, increment reference count • When removed from list, decrement reference count & remove from list • When count goes to zero, delete.
Bridge Traffic • Given a one lane bridge that holds 3 cars, implement: • ArriveBridge(direction) – blocks until safe to travel • CrossBridge(direction) – crosses bridge • ExitBridge(direction) – exits the bridge in the direction • Need to ensure: • No more than 3 cars on the bridge at once • All cars go in the same direction • Every once in while the direction switches
Worker Threads • Problem: • Requests come in • Work done by several threads from a pool • One thread combines results and returns • How do you do this?
Worker Threads (2) • Thread Pools – useful if thread creation is expensive (as it is on Windows NT, or with kernel threads) • Have high/low water mark for number of threads. • Have queue of work items. • Is consumer / producer, but consumer must signal the correct thread when done • May need to wait for multiple threads
Worker Threads (2) • Each work item has a semaphore • Worker thread signals when done • Client thread initializes to # of tasks, waits on semaphore • When client arrives: • Checks # of available threads. • If #avail < #needed, create one up to MAX_THREADS • When thread finishes, if no work item, and #threads > MIN_THREADS, sleep for a while then exit.
Invariants • Useful technique • Have an invariant that is true when a lock is acquired or signaled • E.g. list is non-empty • Linked list has no loops • Allows for easier verification of code
How do you choose a style? • Monitors • Good for write contention • Small amount of data • Short amount of processing time • Need signaling / waiting • Condition Variables • Like monitors, but without language support • More flexible semantics
Choosing style(2) • Mutexes • Good when no waiting is needed, just mutual exclusion • There are tools to help find when mutexes aren’t used properly (Eraser) • Reader/Writer locks • Good when doing mostly reading, but occasionally writing • Under heavy use may have starvation problems • More expensive for common case than a mutex (24 cycles vs 12 cycles)
Choosing a Style (3) • Semaphores • Good for complex situations: • Multiple accessors at once • Waiting for multiple things to happen • Good for counting objects • E.g. number of threads, elements in a buffer
Choosing What to Synchronize • Given a linked list, what do you use? • A mutex for the whole list? • A mutex for each element? • A mutex for a group of elements? (using a hash) • More mutexes • Higher performance • More complexity • Fewer Mutexes • Lower performance (more unnecessary waiting) • Simplified code
Other options • Cheat – don’t always synchronize: InitDone = false; … If (!InitDone) { lock(mutex); if (!InitDone) { DoInitialization(); InitDone = true; } release(mutex); }
Other Options • Lock just some fields of a record • Caveat: depending on how fields are laid out, the processor may not be able to access them safely • Example: Struct foo { Char a; // no lock needed Char b; // lock needed } • foo.a = 3 does this: Ld r1, foo Movb r1, 3 St foo, r1 • B may be clobbered.