In: Computer Science
How is a semaphore initialized when used as a i) a lock() ii) a CV?
Locks and condition variables are an attempt to implement monitors in languages that do not have them. Normally, monitors are part of the language definition and there needs to be syntax to allow programmers to declare a monitor. The main reason that it has to be part of a language is that normal languages can not enforce the mutual exclusiveness of monitor procedure calls. However, you can attempt to get similar behavior by using semaphores.
To initialize a "lock" with a counting semaphore (so that code segments can be implemented atomically), one sets the initial value of the semaphore to 1. Notice that doing so will allow the first thread that calls P() on the semaphore to proceed but all other calls to P() to block until V() is called.
Lock Program:
Lock::Lock() // Constructor
{ value = 1; numSleepers = 0; // Number of process blocked on this semaphore processID = -1; // No process holds this lock mutex = new Semaphore( 1 ); // Initialize semaphore to 1. sleep = new Semaphore( 0 ); // Initialize semaphore to 0. } Lock::Acquire() // Acquire a lock { while ( 1 ) { mutex->P(); if ( value <= 0 ) { numSleepers++; mutex->V(); sleep->P(); } else { value--; processID = process->getPID(); // Record PID of process mutex->V(); break; // exit while loop } } } Lock::Release() // Release a lock { mutex->P(); value++; if ( value > numSleepers ) exit(); // abort if release not used properly numSleepers--; sleep->V(); // Wake up one sleeper mutex->V(); }
CV program:
procedures to go through.
CV::CV( Lock *lock1 ) // Constructor { lock = lock1; // The associated lock with this condition variable numSleepers = 0; // number of sleepers on this CV. CV_sleep = new Semaphore( 0 ); mutex = new Semaphore( 1 ); } CV::Wait() { mutex->P(); // quit if process does not have lock if ( lock->processID != process->GetPID() ) exit(); numSleepers++; lock->Release(); // Release lock associated with this CV. mutex->V(); CV_sleep->P(); // Sleep lock->Acquire(); // When woken up, reacquire lock } CV::Signal() { mutex->P(); // quit if process does not have lock if ( lock->processID != process->GetPID() ) exit(); if( numSleepers > 0 ) { CV_sleep->V(); // Wake single process up numSleepers--; } mutex->V(); }