January 29, 2004 Adrienne Noble Week 4 January 29, 2004 Adrienne Noble
Questions? Important dates: Homework 3 – Due tomorrow, Jan 30 Project 2a – Due Monday, Feb 2 Midterm – Friday, Feb 6 Project 2b – Due Wednesday, Feb 11
Typedef Simple a shortcut name to a type Use Examples: typedef type shortcutName Examples: typedef int myIntType; typedef struct { // struct variables… } structName; Typedef char* pointerToChar; Typedef char *pointerToChar;
Mutexes Just a simple lock on shared data Only allows one thread to access the shared data at a time Two functions: lock and unlock Basic Idea: Get lock (call lock function) Access shared data Give up lock (call unlock function)
Mutex Example You should be able to think of all sorts of uses for a mutex… Withdrawing money from a bank account Reserving a ticket
Semaphores More powerful than mutexes Two functions: wait (or P) and signal (or V) Simplest form: a binary semaphore Works just like a mutex Semaphore counter is initialized as 1 A thread calls wait (or P) if the counter is positive, the thread subtracts 1 from the counter and gets the lock If the counter is 0, the thread is suspended and put in the semaphore’s waiting queue A thread calls signal (or V) If the queue is empty, the thread adds 1 to the counter and continues If the queue has waiting threads, the thread adds 1 to the counter and one of the threads is taken off the queue, then continues You can implement your mutex as a semaphore or as a lock… either way is fine. Why?
Semaphore Example Can also be used to let more than one thread in at once A ferry only allows 100 passengers on board The counter is initialized to 100 Each passenger that gets on the ferry will decrement the counter by 1. After 100 passengers, the counter will be at 0, and all further passengers will be put on the queue. If a passenger gets off the ferry, he takes one person off the queue and lets them get on the ferry. If no one is on the queue, he increments the counter by 1.
Condition Variables Used to let threads wait for a certain condition or event to occur while holding a lock (often a monitor) Three functions: wait, signal, and broadcast Basic Idea: Thread with the lock calls wait The thread gives up the lock, then goes to sleep on the condition variable’s queue Someone signals to say that the event or condition has occurred A thread wakes up from the queue, obtains the lock again, and then continues
Condition Variable Example A server has a bunch of threads waiting to handle incoming requests Those threads wait on a condition variable When an incoming request comes in, the controller thread signals that there is work to do A thread is woken up and goes to handle the request What might you call this architecture? Threadpool
Another Condition Variable Example How would you use broadcast? Alarm clock example from homework? Lots of people waiting on “timer” queue, the shortest time is up but you don’t know whose time it is – just wake everyone up and let them figure it out
Monitors A higher level way to deal with shared data Allows you to make an entire object protected by a mutex A monitor controls all access to the class by letting only one thread access the class instance at once
Monitor Example Usually requires language support In Java, any synchronized class is controlled by a monitor Hidden from the programmer, but anytime a thread wants to access anything in the class, the monitor makes it first obtain a lock Condition variables are often used in monitors to allow other threads to access the monitor while one thread waits for an event to occur
Picture from Lecture Everything goes onto ready queue before actually getting run! What exactly is a ready queue?
Thread Scheduler in Linux Doesn’t use a FIFO queue like we did Measures a thread’s “goodness” (yes, that’s what they really call it…) Goodness algorithm (where p is the thread being checked) if ( p->policy != SCHED_OTHER ) return 1000 + p->rt_priority if ( p->counter == 0 ) return 0; if ( p->mm == prev->mm ) return p->counter + p->priority + 1; return p->counter + p->priority; The thread with the highest goodness is chosen to run next (p->policy != SCHED_OTHER) means that it gets a big bonus if it’s a real-time process (p->counter == 0) means that if it’s used up all it’s time, it must wait to run – it has no priority (p->mm == prev->mm) means if it’s sharing some of the previous processes memory, it gets a little bonus