Programmation Concurrente en J AV A
T MDocument en cours d’´elaboration issu de plusieurs versions ´elabor´ees principalement par J-P. Rigault, puis par M.
Cosnard, J-F. Lalande, et F. Peix, et enfin aujourd’hui par I. Sau et M. Syska.
TP2 : Exclusion mutuelle et s´emaphores en Java
14 F´evrier 2007
1 Gestion des entr´ees/sorties d’un parking
Dans cet exercise on souhaite compter les entr´ees et sorties des v´ehicules dans un parking pour afficher le nombre de places occup´ees. Ici, pour simplifier on ne comptera que les entr´ees. Le fonctionnement du parking est simple:
• Il y a2portes d’entr´ee au parking (P dans le cas g´en´eral).
• Le parking a capacit´e2N (P ·N dans le cas g´en´eral).
• N voitures entrent par chaque porte du parking.
Le but de cet exercice est de compter les voitures qu’il y a dans le parking en utilisant une seule vari- able partag´ee. On va utiliser l’algorithme de Peterson pour garantir l’exclusion mutuelle entre les threads.
Id´ee de l’algorithme de Peterson (avec 2 threads):
/ / Chaque t h r e a d a 3 ” f l a g s ” e n t i e r s ( p a r t a g ´e s ) e t s o n i d e n t i f i c a t e u r : / / m o n f l a g , f l a g a u t r e t h r e a d , d e r n i e r , m o n i d
p r i v a t e v o i d e n t r e r s e c t i o n c r i t i q u e ( . . . ){ m o n f l a g <− 1
d e r n i e r <− m o n i d
w h i l e ( f l a g a u t r e t h r e a d ==1 && d e r n i e r == m o n i d ) {}
}
p r i v a t e v o i d s o r t i r s e c t i o n c r i t i q u e ( . . . ){
Corps du programme:
i m p o r t j a v a . u t i l . c o n c u r r e n t . a t o m i c . * ;
/ / On d e f i n i t une c l a s s e p o u r p o u v o i r p a r t a g e r l e c o m p t e u r : p u b l i c c l a s s m i n t e g e r {
p r i v a t e i n t v a l u e ; p u b l i c m i n t e g e r ( ){
v a l u e = 0 ; }
p u b l i c v o i d s e t v a l u e ( i n t n e w v a l u e ){
t h i s . v a l u e = n e w v a l u e ; }
p u b l i c i n t g e t v a l u e ( ){ r e t u r n t h i s . v a l u e ; }
}
p u b l i c c l a s s P o r t e e x t e n d s T h r e a d { . .
}
p u b l i c c l a s s P a r k i n g P e t e r s o n {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { . . .
} }
2 Le coiffeur dormeur
Il s’agit encore d’un de ces probl`emes de synchronisation mis sous une forme ”plaisante”. Mais celui-ci est encore plus s´erieux que le probl`eme classique des philosophes1, car on en trouve une application presque directe dans certains m´ecanismes des syst`emes d’exploitation (comme l’ordonnancement des acc`es disque).
Description du probl`eme:
• Un coiffeur poss`ede un salon avec un si`ege de coiffeur et une salle d’attente comportant un nombre fixeF de fauteuils.
• S’il n’y a pas de client, le coiffeur se repose sur son si`ege de coiffeur.
• Quand un client arrive:
– s’il trouve le coiffeur endormi, il le r´eveille, s’assoit sur le si`ege de coiffeur et attend la fin de sa coupe de cheveux.
– si le coiffeur est occup´e lorsque le client arrive, le client s’assoit et s’endort sur une desCchaises de la salle d’attente.
– si le coiffeur est occup´e lorsque le client arrive et la salle d’attente est pleine, le client repasse plus tard.
• Lorsque le coiffeur a termin´e une coupe de cheveux, il fait sortir son client courant et va r´eveiller un des clients de la salle d’attente.
• Si la salle d’attente est vide, le coiffeur se rendort sur son si`ege jusqu’`a ce qu’un nouveau client arrive.
Le but de de cet exercice est d’associer une thread au coiffeur ainsi qu’`a chaque client et de programmer une s´eance de coiffeur dormeur en Java, et d’utiliser les s´emaphores pour garantir l’exclusion mutuelle parmi les processus.
2.1 Avec des s´emaphores
Pour cet exercice on utilisera les s´emaphores de la JDK 1.5. On ´ecrira une classe pour le coiffeur (Bar- berSemaphore) et une classe pour les clients (CustomerSemaphore). L’id´ee est que la communication se fasse au travers de s´emaphores, bloquant l’ex´ecution des threads quand cela est n´ecessaire.
i m p o r t j a v a . u t i l . c o n c u r r e n t . Sem a phore ;
/ / ========================================================================
/ / B a r b e r S e m a p h o r e i n J a v a
/ / −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
/ / Usage :
/ / j a v a c B a r b e r S e m a p h o r e . j a v a
/ / j a v a B a r b e r S e m a p h o r e n b C h a i r s n b C u s t o m e r s
/ / ========================================================================
/ / S emaph ore s e m a p h o r e = new Sem aphor e ( c a p a c i t e ) ;
/ / Method P on Semaphore ” s e m a p h o r e ” : s e m a p h o r e . a c q u i r e ( ) ; / / Method V on Semaphore ” s e m a p h o r e ” : s e m a p h o r e . r e l e a s e ( ) ; / / S i m u l a t e b a r b e r b e h a v i o r s w i t h Sem apho re :
c l a s s B a r b e r S e m a p h o r e e x t e n d s T h r e a d { . . .
}
c l a s s C u s t o m e r S e m a p h o r e e x t e n d s T h r e a d { . . .
}
p u b l i c c l a s s S e a n c e {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { . . .
} }
ANNEXE: Solution de la partie 4 du TP1
p a c k a g e TD1 ;
//========================================================================
/ / Showing t h a t s y n c h r o n i z a t i o n b e t w e e n t h r e a d s i s n e e d e d
//−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
/ / Usage :
/ / j a v a c N o n S y n c h r o T h r e a d s . j a v a
/ / j a v a N o n S y n c h r o T h r e a d s n l o o p n s i z e | g r e p BAD
//========================================================================
/ / W r i t e t h e same number i n a g i v e n a r r a y : c l a s s M y T h r e a d N o n S y n c h r o W r i t e e x t e n d s T h r e a d {
i n t i d ; / / t h i s w r i t e r i d
i n t n l o o p ; / / number o f i t e r a t i o n s i n t [ ] t a b ; / / a s h a r e d a r r a y
p u b l i c M y T h r e a d N o n S y n c h r o W r i t e ( i n t i d , i n t n l o o p , i n t [ ] t a b , S t r i n g name ) { s u p e r ( name ) ;
t h i s . i d = i d ;
t h i s . n l o o p = n l o o p ; t h i s . t a b = t a b ; }
p u b l i c v o i d r u n ( ) { t r y {
f o r ( i n t i = 0 ; i < n l o o p ; i ++) {
f o r ( i n t j = 0 ; j < t a b . l e n g t h ; j ++) { t a b [ j ] = i d ;
s l e e p ( 5 0 ) ; / / y i e l d ( ) ; }
}
} c a t c h ( E x c e p t i o n e ) {
S y s t e m . e r r . p r i n t l n ( ” E x c e p t i o n i n M y T h r e a d N o n S y n c h r o W r i t e ” + e ) ; }
/ / V e r i f y t h a t a l l n u m b e r s o f a g i v e n a r r a y a r e e q u a l :
c l a s s MyThreadNonSynchroRead e x t e n d s T h r e a d { i n t n l o o p ; / / number o f i t e r a t i o n s
i n t [ ] t a b ; / / a s h a r e d a r r a y
p u b l i c MyThreadNonSynchroRead ( i n t n l o o p , i n t [ ] t a b , S t r i n g name ) { s u p e r ( name ) ;
t h i s . n l o o p = n l o o p ; t h i s . t a b = t a b ; }
p u b l i c v o i d r u n ( ) { t r y {
f o r ( i n t i = 0 ; i < n l o o p ; i ++) { i n t sum = 0 ;
f o r ( i n t j = 0 ; j < t a b . l e n g t h ; j ++) { sum += t a b [ j ] ;
}
i f ( sum % t a b . l e n g t h ! = 0 ) {
S y s t e m . o u t . p r i n t l n ( ”BAD a t i = ” + i + ” sum = ” + sum ) ; }
}
} c a t c h ( E x c e p t i o n e ) {
S y s t e m . e r r . p r i n t l n ( ” E x c e p t i o n i n MyThreadNonSynchroRead ” + e ) ; }
S y s t e m . o u t . p r i n t l n ( ” End o f ” + t h i s . getName ( ) ) ; r e t u r n ;
} }
p u b l i c c l a s s N o n S y n c h r o T h r e a d s {
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { t r y {
/ / r e a d command−l i n e a r g u m e n t s i f ( a r g s . l e n g t h ! = 2 ) {
S y s t e m . e r r . p r i n t l n ( ” u s a g e : N o n S y n c h r o T h r e a d s n l o o p n s i z e ” ) ; S y s t e m . e x i t ( 1 ) ;
}
i n t n l o o p = I n t e g e r . p a r s e I n t ( a r g s [ 0 ] ) ; i n t n s i z e = I n t e g e r . p a r s e I n t ( a r g s [ 1 ] ) ;
S y s t e m . e r r . p r i n t l n ( ” S t a r t i n g N o n S y n c h r o T h r e a d s f o r n l o o p = ” + n l o o p + ” and n s i z e = ” + n s i z e ) ;
i n t [ ] t a b = new i n t [ n s i z e ] ;
/ / t h r e a d c r e a t i o n
T h r e a d t h 1 = new M y T h r e a d N o n S y n c h r o W r i t e ( 0 , n l o o p , t a b , ” W r i t e r 0 ” ) ; T h r e a d t h 2 = new M y T h r e a d N o n S y n c h r o W r i t e ( 1 , n l o o p , t a b , ” W r i t e r 1 ” ) ; T h r e a d t h 3 = new MyThreadNonSynchroRead ( n l o o p , t a b , ” R e a d e r 0 ” ) ;
/ / s t a r t i n g t h r e a d s t h 1 . s t a r t ( ) ;
t h 2 . s t a r t ( ) ; t h 3 . s t a r t ( ) ;
} c a t c h ( E x c e p t i o n e ) { / / r e p o r t any e x c e p t i o n s
S y s t e m . e r r . p r i n t l n ( ” E x c e p t i o n i n N o n S y n c h r o T h r e a d s . main ” + e ) ; }
} }