Post on 03-Jan-2016
4061 Session 23 (4/10)
Today
• Reader/Writer Locks and Semaphores
• Lock Files
Today’s Objectives• Describe semaphores and reader/writer
locks
• Pseudo-code a barrier using synchronization primitives
• Write multi-process code that coordinates file writes to avoid race conditions or interleaved output
• Write code that uses a lockfile to ensure that a single instance is running
Admin
• Scholarships– http://www.cs.umn.edu/academics/undergraduate/scholarships.php
• Quiz 4
• Homework 4
Readers and Writers Problem
• Imagine a database system with many processes trying to read and write concurrently– It’s ok if several processes read data at the
same time– But once a process starts to write, it needs a
mutex
• So perhaps we want to improve on the efficiency of enforcing mutex on all operations…
Strong Reader Synchronization
• One solution:– Readers
• First reader locks the write mutex.• Subsequent readers allowed in (increment
counter). • Last reader out releases the write mutex
– Writers• Lock write mutex, write, unlock
• Problems?
Strong Writer Synchronization
• Alternate solution:– Incoming readers are queued behind any
waiting writers
POSIX Read-Write Locks
• Calls are very similar to mutex
• The main difference is that you declare whether you are attempting to obtain a read lock or a write lock (through different calls)
Semaphores
• Like an integer, but with some special properties for synchronization– Initialization: any value. Subsequent use:
restricted to increment and decrement. Cannot read value.
– When a thread decrements a semaphore and the result is negative, the thread blocks until the semaphore is no longer negative.
– When a thread increments a semaphore, one of the waiting threads (if any) gets unblocked.
Semaphore Operations
• Operations have many names– decrement and increment– down and up– Dutch: p and v– Robbins Book: wait and signal– Posix: wait and post
• We’ll use wait and signal unless we’re discussing posix code
Semaphore as Mutex
s = Semaphore(1)
Thread 1:
s.wait()
// critical section
s.signal()
Thread 2:
s.wait()
// critical section
s.signal()
Exercise: Barriers (1)
Exercise: Barriers
• Say we have n threads. Our requirement is that all n threads finish their work before our program moves forward.
• All threads must run the code:rendezvouscritical point
• No thread can execute “critical point” until all threads have executed rendezvous
• There are n threads. You can use this variable.• When the first n-1 threads “arrive” they should
block until the nth thread arrives, at which point all threads should proceed.
Synchronizing I/O
• By default, Unix allows simultaneous, unrestricted access to files
• Recall: each process with an open file gets its own entry in the open file table, and its own offset
Concurrent File Access
• If two processes have the same file open for reading, there are no problems
• If one reads and another writes, the reader will see the results of write operations immediately
• If both are writing to the file, we can have race conditions
Race Condition in File Writes
Process A
lseek 100
(context switch)
Write 50 bytes
Process B
lseek 100
write 100 bytes
File Locking
• How do we coordinate file access?– We can use system calls to lock files– We can lock whole files, or just sections of
files– We can lock files for read, or for write
Mandatory vs. Advisory Locking
• Mandatory– Lock enforced by the OS– Prevent read() and write() from occurring when a file
is locked– Works by removing the execute permission for group
and setting the setgid bit– Not on by default. Need to mount the filesystem with
“-o mand”
• Problems?– Non-privileged processes can hold locks indefinitely.
Root cannot override (except by killing the process).
Advisory Locking
• Advisory– Not enforced by the OS– Thus, works for cooperating processes only
• Problems?– Non-cooperating processes may not ask for
the lock
• Generally, this is the preferred/standard method for file locking
Locking: Read/Write
• Read locks can be shared, but write locks cannot– If there’s already a read lock, you can add
another read lock, but not a write lock– If there’s already a write lock, you cannot add
another lock of any kind
Lockfiles
• Open a file with O_CREAT | O_EXCL– Atomic, and fails if the file already exists
• For a singleton daemon, if the lockfile creation fails with EEXIST, then the singleton is already running
• What if the daemon crashed without removing the lockfile?– Daemon writes its pid to the file– If daemon starts up and finds the file, it reads the pid– If the process does not exist (use kill(pid, 0)) then
delete the file and try again
Lockfiles (2)
• But, the sequence (read file, check for process, delete file) is not atomic, and therefore has a race condition– What can happen?
• Lock the file before reading it– Request exclusive lock– Read file– If the process does not exist, write your own
pid, then release lock