17
Lecture 6: Monitors & Semaphores

Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Embed Size (px)

Citation preview

Page 1: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Lecture 6:

Monitors & Semaphores

Page 2: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Monitor

Contains data and procedures needed to allocate shared resources

Accessible only within the monitor

No way for threads outside monitor to access monitor data

Resource allocation using Monitors

Thread must call monitor entry routine

Mutual exclusion is rigidly enforced at monitor boundary

A thread that tries to enter monitor when it is in use must wait

Monitor

Operating Systems - Deitel & Associates - 2004

Page 3: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

lock( ) vs. monitor( )

Both lock( ) and monitor( ) are methods of enforcing mutual exclusion in modern programming languages such as C# and Java. In the .NET environment, lock( ) is preferred since it manages the thread queue.

Like the lock keyword, monitors prevent blocks of code from simultaneous execution by multiple threads. The Enter method allows one and only one thread to proceed; all other threads are blocked until the executing thread calls Exit. This is just like using the lock keyword. In fact, the lock keyword is implemented with the Monitor class.

Using the lock is generally preferred over using the Monitor class directly, both because lock is more concise, and because lock ensures that the underlying monitor is released, even if the protected code throws an exception. This is accomplished with the finally keyword, which executes its associated code block regardless of whether an exception is thrown.

http://msdn.microsoft.com/en-us/library/ms173179%28VS.80%29.aspx

Page 4: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

using System;using System.Threading;namespace monitor_demo_02{ public class Test { static int count = 0; static void Main() { ThreadStart job = new ThreadStart(ThreadJob); Thread thread = new Thread(job); thread.Start(); for (int i = 0; i < 5; i++) { int tmp = count; Console.WriteLine("Read count={0}", tmp); Thread.Sleep(50); tmp++; Console.WriteLine("Incremented tmp to {0}", tmp); Thread.Sleep(20); count = tmp; Console.WriteLine("Written count={0}", tmp); Thread.Sleep(30); }

thread.Join(); Console.WriteLine("Final count: {0}", count); Console.ReadKey(); }

Multi-Threaded Demono Monitor

http://www.yoda.arachsys.com/csharp/multithreading.html

Page 5: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

static void ThreadJob() { for (int i = 0; i < 5; i++) { int tmp = count; Console.WriteLine("\t\t\t\tRead count={0}", tmp); Thread.Sleep(20); tmp++; Console.WriteLine("\t\t\t\tIncremented tmp to {0}", tmp); Thread.Sleep(10); count = tmp; Console.WriteLine("\t\t\t\tWritten count={0}", tmp); Thread.Sleep(40); } } }}

Multi-Threaded Demo - concluded

Page 6: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Read count=0 Read count=0 Incremented tmp to 1 Written count=1Incremented tmp to 1Written count=1 Read count=1 Incremented tmp to 2Read count=1 Written count=2 Read count=2Incremented tmp to 2 Incremented tmp to 3Written count=2 Written count=3Read count=3 Read count=3 Incremented tmp to 4 Written count=4Incremented tmp to 4Written count=4 Read count=4Read count=4 Incremented tmp to 5 Written count=5Incremented tmp to 5Written count=5Read count=5Incremented tmp to 6Written count=6Final count: 6

Multi-Threaded Sample Output

Page 7: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

using System;using System.Threading;

namespace monitor_demo_01{ public class Test { static int count = 0; static readonly object countLock = new object();

static void Main() { ThreadStart job = new ThreadStart(ThreadJob); Thread thread = new Thread(job); thread.Start();

for (int i = 0; i < 5; i++) { Monitor.Enter(countLock); int tmp = count; Console.WriteLine("Read count={0}", tmp); Thread.Sleep(50); tmp++; Console.WriteLine("Incremented tmp to {0}", tmp); Thread.Sleep(20); count = tmp; Console.WriteLine("Written count={0}", tmp); Monitor.Exit(countLock); Thread.Sleep(30); } thread.Join(); Console.WriteLine("Final count: {0}", count); Console.ReadKey(); }

Monitor Demo

Page 8: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

static void ThreadJob() { for (int i = 0; i < 5; i++) { Monitor.Enter(countLock); int tmp = count; Console.WriteLine("\t\t\t\tRead count={0}", tmp); Thread.Sleep(20); tmp++; Console.WriteLine("\t\t\t\tIncremented tmp to {0}", tmp); Thread.Sleep(10); count = tmp; Console.WriteLine("\t\t\t\tWritten count={0}", tmp); Monitor.Exit(countLock); Thread.Sleep(40); } } }}

Monitor Demo - concluded

Page 9: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Read count=0Incremented tmp to 1Written count=1 Read count=1 Incremented tmp to 2 Written count=2Read count=2Incremented tmp to 3Written count=3 Read count=3 Incremented tmp to 4 Written count=4Read count=4Incremented tmp to 5Written count=5 Read count=5 Incremented tmp to 6 Written count=6Read count=6Incremented tmp to 7Written count=7 Read count=7 Incremented tmp to 8 Written count=8Read count=8Incremented tmp to 9Written count=9 Read count=9 Incremented tmp to 10 Written count=10Final count: 10

Monitor Demo Sample Output

Page 10: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Semaphores

Software construct that can be used to enforce mutual exclusion

Contains a protected variable

Can be accessed only via wait and signal commands

Also called P and V operations, respectively

Semaphores

Page 11: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Binary semaphore: allow only one thread in its critical section at any time...

Wait operation

If no threads are waiting, allow thread into its critical section

Decrement protected variable (to 0 in this case)

Otherwise place in waiting queue

Signal operation

Indicate that thread is outside its critical section

Increment protected variable (from 0 to 1)

A waiting thread (if there is one) may now enter

Binary Semaphore

Page 12: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Counting semaphores

Initialized with values greater than one

Can be used to control access to a pool of identical resources

Decrement the semaphore’s counter when taking resource from pool

Increment the semaphore’s counter when returning it to pool

If no resources are available, thread is blocked until a resource becomes available

Counting Semaphores

Page 13: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Semaphores

A semaphore is a protected variable whose value can be accessed and altered only by the operations P( ) and V( ) and an initialization operation SemaphoreInit( ). Binary semaphores can have values true or false while counting semaphores can have non-negative integer values.

function P(S:semaphore) if S>0 then S:=S-1; else wait_for(S); end if;end P;

function V(S:semaphore) if waiting_for(S) then release_for(S); else S:=S+1; end if;end V;

wait_for(S) adds the process calling P(S) to a queue.

waiting_for(S) is a boolean function that checks to see if the queue is empty.

release_for(S) releases the process waiting at the front of the queue.

Page 14: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Using Semaphores: Mutual Exclusion

program example_one is active : semaphore;

procedure P1 isbegin while true do begin stuff; P(active); critical_region; V(active); end;end P1;

procedure P2 isbegin while true do begin stuff; P(active); critical_region; V(active); end;end P2;

begin example_one semaphore_init(active,1); parbegin P1; P2; parend;end example_one;

The semaphore active is set to one (1) and acts to control the process’s access to its critical section.

Page 15: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Using Semaphores: Producer-Consumer

Interprocess communication occurs when one process passes data to another process. This is more complex than a procedure call with parameter passing since the two processes do not necessarily share the same address space. The processes must be synchronized which means that the data transfer must occur in the proper time sequence.

procedure producer is nextvalue : integer;begin while true do begin calculate(nextvalue); P(access_numbuffer); numbuffer:=nextvalue; V(access_numbuffer); V(numbuffer_loaded); end;end producer;

procedure consumer is nextvalue : integer;begin while true do begin P(numbuffer_loaded); P(access_numbuffer); nextvalue:=numbuffer; V(access_numbuffer); make_use_of(nextvalue); end;end consumer;

Page 16: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Mutual Exclusion with Test-and-Set

When the computer hardware can be used to support the enforcement of mutual exclusion, the complexity of the resulting software is greatly reduced. The indivisible instruction testandset(a,b)reads the value of a boolean b, copies it into a and then sets b to true all within the span of a single uninterruptible instruction.

procedure P1 no_P1 : boolean;begin while true do begin no_P1:=true; while no_P1 do testandset(no_P1,go); critical_region; go:=false; other_stuff; end;end P1;

procedure P2 no_P2 : boolean;begin while true do begin no_P2:=true; while no_P2 do testandset(no_P2,go); critical_region; go:=false; other_stuff; end;end P2;

Page 17: Lecture 6: Monitors & Semaphores. Monitor Contains data and procedures needed to allocate shared resources Accessible only within the monitor No way for

Summary

Monitors hold data to be protected from concurrent asynchrononous access

Monitors can be used to manage shared resources of any type

In C# lock( ) is preferred when enforcing mutual exclusion of shared data

Semaphores require special hardware implementation (binary and counting)

Test-and-Set is an uninteruptable instruction