Topics Topics � Thread Programming (Chapter 12) Threads & Locks – Advantages/Disadvantages Threads & Locks – Mutex Locks – Semaphore Locks – Condition Variables Srinidhi Varadarajan � File Locking Mechanisms Advantages of threads Disadvantages of Threads Advantages of threads Disadvantages of Threads � Lower context switching overhead � Shared state – Global variables are shared between threads: � Shared state. Inadvertent modification of shared variables can be disastrous – Allows concurrent instances of the server to communicate easily with each other � Many library functions are not thread safe. – Library functions that return pointers to � Linux supports the POSIX threads standard. internal static arrays are not thread safe. E.g. – PTHREADS library gethostbyname() used for DNS lookup – Portable across most UNIX platforms. � Lack of robustness: If one thread crashes, – FSF project has largely ported pthreads to windows the whole application crashes platforms as well. Thread state Thread Synchronization: Thread Synchronization: Mutex Mutex Thread state � How can a thread ensure that access/updates to � Each thread has its own stack and local shared variables is atomic? variables � How can a thread ensure that it is the only thread � Globals are shared. executing some critical piece of code? � File descriptors are shared. If one thread – Need a mechanism for thread coordination and synchronization closes a file, all other threads can’t use – Enter semaphores and mutex calls the file � Mutex: Mutual Exclusion Lock. � I/O operations block the calling thread. – Threads can create a mutex and initialize it. Before – Some other functions act on the whole entering a critical region, lock the mutex. process. For example, the exit() function – Unlock the mutex after exiting the critical region operates terminates the entire and all associated threads. Application Layer 1
Thread Synchronization: Semaphores Conditional Variables Thread Synchronization: Semaphores Conditional Variables � A set of threads use a mutex to allow � A mutex allows one thread to enter a serial access to a critical region. critical region. A semaphore can allow � Once a thread enters a critical region, it some N threads to enter a critical region. needs to check for a condition to occur – Used when there is a limited (but more than 1) before proceeding. number of copies of a shared resource. – This scenario is prone to deadlocks. A thread � Can be dynamically initialized. can’t busy wait checking for the condition. Why? (Hint: what if the condition is set within – Thread calls a semaphore wait function before a mutex protected region) it enters a critical region. � Wasteful solution: � Semaphore is a generalization of a mutex. – Thread enters mutex region, checks condition. If condition has not occurred, release mutex and repeat the process after some time File Locking File Locking Conditional Variables Conditional Variables � A condition variable allows a thread to � File locking functions allow you to: release a mutex and block on a condition – Lock entire files for exclusive use atomically. – Lock regions in a file � When the condition is signaled, the – Test for locks held by other programs thread is allowed to reacquire the mutex � Function: and proceed. – Two forms of signaling exist based on how – flock(int fd, int operation) where operation is: many threads are blocked on the condition. • LOCK_SH: Shared Lock – Either one thread may be allowed to proceed • LOCK_EX: Exclusive Lock. or all threads blocked on the condition are • LOCK_UN: Unlock allowed to proceed. • LOCK_NB: Non blocking lock. Returns –ve result if lock can’t be obtained Record Locking Record Locking Record Locking Record Locking Type of lock desired: (l_type) F_RDLCK: A shared read lock � The flock function locks the entire file. Record F_WRLCK: An exclusive write lock locking can be used to lock regions within a file F_UNLCK: Unlocking a region � Record locking uses the flock structure. Lock l_len bytes starting from #include <sys/types.h> (l_whence + l_start) #include <unistd.h> #include <fcntl.h> l_whence: SEEK_SET, SEEK_CUR, struct flock { off_t l_start; /* starting offset */ SEEK_END off_t l_len; /* len = 0 means until EOF */ To lock entire file set: l_start to 0, l_whence pid_t l_pid; /* lock owner */ short l_type; /* F_RDLCK, F_WRLCK, F_UNLCK*/ to SEEK_SET, and l_len to 0. short l_whence; /* type of l_start */ }; Application Layer 2
Record Locking: Example Record Locking: Example Record Locking Record Locking struct flock lock; � int fcntl(int filedes, int cmd, FILE* myFile; struct flock *lock); int fd; if(( fd = creat("templock", FILE_MODE)) < 0 ) /* error */; � filedes: File descriptor lock.l_len = 0; lock.l_start = 0; � cmd: lock.l_whence = SEEK_SET; – F_GETLK: Returns the lock struct of the lock preventing a lock.l_type = F_WRLCK; file lock or sets the l_type to F_UNLCK on no obstruction fcntl(fd, F_SETLKW, lock); – F_SETLK: Non-Blocking call to lock or unlock a region. myFile = fopen("mylog", "a"); Depends on the command inside the flock struct. Returns fprintf(myFile, "Write\n"); –1 if lock is held by someone else fclose(myFile); – F_SETLKW: Blocking version of F_SETLK lock_l_type = F_UNLCK; fcntl(fd, F_SETLKW, lock); � struct flock *lock Application Layer 3
Recommend
More recommend