Goal is to provide programming tools which reduce the likelihood of errors for this type of code. The idea is that if the compiler writer can get the process synchronization code right, then code using that language will be much less error-prone.
Critical Regions:
Code example:
code fragment 1: code fragment 2: VAR v: SHARED type; VAR v: SHARED type; ... ... REGION v DO s1; REGION v DO s2;The compiler then generates the code to insure that s1 and s2 are not executed simultaneously, e. g.,
/ | ... | wait( v_mutex ); REGION v DO s; < s; | signal( v_mutex ); | ... \Critical region solution is not foolproof. Consider
code fragment 1: code fragment 2: ... ... REGION x DO REGION y DO ... ... REGION y DO REGION x DO s1; s2;(i.e., deadlock can occur).
Another example, but this time using conditional critical regions.
Here is a solution to the bounded buffer problem using conditional critical regions:
VAR buffer SHARED RECORD pool: ARRAY[ 1..n-1 ] OF item; count, in, out: integer; END; producer: REGION buffer WHEN count < n DO BEGIN <--- this means that the pool[ in ] = nextp; process cannot enter in = in + 1 MOD n; the region unless the count = count + 1; condition is true. This END; is in addition to the mutual exclusion normally consumer: provided by regions. REGION buffer WHEN count > 0 DO BEGIN nextc = pool[ out ]; out = out + 1 MOD n; count = count -1; END;This provides a neat, simple, elegant solution to the problem.
(A historical comment: the problem with providing these types of language constructs to simplify code has not really caught on. The problem is not creating new compilers for new languages -- this process is well understood. The problem is that the next process synchronization problem is likely to have some unique feature so that the provided language construct, such as conditional critical regions, does not handle well. And the code gets confusing and complex and hence error-prone all over again.)
Monitors
Another attempt to reduce errors.
Example: Dining Philosophers. This implements the "grab both chopsticks" solution.
Each Philosopher:
REPEAT forever wait( rnd( thinktime ) ); dp.pickup( i ); wait( rnd( eattime ) ); dp.putdown( i ); END;Monitor Code:
TYPE dp = MONITOR VAR state: ARRAY[ 0..4 ] OF ( thinking, hungry, eating ); VAR self: ARRAY[ 0..4 ] OF condition; { only ops on condition var } { are wait and signal } PROC pickup( i: 0..4 ); BEGIN state[ i ] = hungry; test[ i ]; IF state[ i ] != eating THEN self[ i ].wait; END; PROC putdown( i: 0..4 ); BEGIN state[ i ] = thinking; test[ i+4 MOD 5 ]; test[ i+1 MOD 5 ]; END; PROC test( k: 0..4 ); BEGIN IF state[ k+4 MOD 5 } != eating AND state[ k+1 MOD 5 ] != eating AND state[ k ] == hungry THEN BEGIN state[ k ] = eating; sefl[ k ]. signal; END END; BEGIN { init } FOR i = 0 TO 4 DO state[ i ] = thinking END;Note: starvation (pun intented) is possible with this solution.
Index | Previous | Next |
---|
Copyright ©2017, G. Hill Price
Send comments to G. Hill Price