Forslag til løsning på oppgavesett for uke 40 Lars Vidar Magnusson November 3, 2011 1 Tråder 1. Lag et program som starter tre ulike tråder (forskjellige trådfunksjoner) som hver av skriver ut en melding før de returnerer. void t h r e a d f u n 1 ( void arg ) p r i n t f ( Thread1\n ) ; void t h r e a d f u n 2 ( void arg ) p r i n t f ( Thread2\n ) ; void t h r e a d f u n 3 ( void arg ) p r i n t f ( Thread3\n ) ; p t h r e a d t thread1, thread2, thread3 ; p t h r e a d c r e a t e (&thread1, NULL, thread fun1, NULL) ; p t h r e a d c r e a t e (&thread2, NULL, thread fun2, NULL) ; p t h r e a d c r e a t e (&thread3, NULL, thread fun3, NULL) ; p t h r e a d j o i n ( thread1, NULL) ; p t h r e a d j o i n ( thread2, NULL) ; p t h r e a d j o i n ( thread3, NULL) ; 1
2. Gjør om på det forrige programmet slik at trådene er av samme type og at meldingen gis som et argument til tråden. void t h r e a d f u n ( void arg ) p r i n t f ( %s \n, ( const char ) arg ) ; p t h r e a d t thread1, thread2, thread3 ; p t h r e a d c r e a t e (&thread1, NULL, thread fun, Thread1 ) ; p t h r e a d c r e a t e (&thread2, NULL, thread fun, Thread2 ) ; p t h r e a d c r e a t e (&thread3, NULL, thread fun, Thread3 ) ; p t h r e a d j o i n ( thread1, NULL) ; p t h r e a d j o i n ( thread2, NULL) ; p t h r e a d j o i n ( thread3, NULL) ; 2 Concurrency 1. Lag et program som benytter tre tråder til å øke et felles heltall på forskjellige tidsintervaller. Det globale heltallet må beskyttes med en valgfri concurrency mekanisme. pthread mutex t global mutex ; int global sum ; void t h r e a d f u n ( void arg ) int num ; int i n t e r v a l ; num = 1 0 ; i n t e r v a l = ( int ) arg ; while (num ) 2
s l e e p ( i n t e r v a l ) ; pthread mutex lock (& global mutex ) ; global sum += 1 ; pthread mutex unlock(& global mutex ) ; p r i n t f ( New Number = %d\n, global sum ) ; p t h r e a d t thread1, thread2, thread3 ; p t h r e a d m u t e x i n i t (&global mutex, NULL) ; p t h r e a d c r e a t e (&thread1, NULL, thread fun, ( void ) 1 ) ; p t h r e a d c r e a t e (&thread2, NULL, thread fun, ( void ) 2 ) ; p t h r e a d c r e a t e (&thread3, NULL, thread fun, ( void ) 3 ) ; p t h r e a d j o i n ( thread1, NULL) ; p t h r e a d j o i n ( thread2, NULL) ; p t h r e a d j o i n ( thread3, NULL) ; pthread mutex destroy(& global mutex ) ; 2. Lag et program som lager 4 ulike typer arbeidstråder. Disse trådene skal simulere produksjon og distrubisjon av en vilkårlig vare. Varen produseres av to ulike deler som må skaffes separat. Dette er oppgaven til de to første trådene som anskaffer hver sin vare og legge den til et delelager. Tiden det tar for innkjøp av de to delene er forskjellig og kan variere fra gang til gang. Den tredje tråden tar regelmessig én av hver av delene fra delelageret og produserer en ny enhet av varen som så blir plassert på lageret. Den siste tråden er ansvarlig for å skaffe kunder og distrubere den produserte varen. Dette er en mer uforutsigbar prosess så her må både tidsintervallet og antallet variere. #define RUNNING 1 #define SHUTDOWN 0 pthread mutex t part1 mutex ; 3
pthread mutex t part2 mutex ; pthread mutex t storage mutex ; int part1 ; int part2 ; int s t o r a g e ; int s t a t u s ; void a c q u i r e p a r t 1 f u n ( void arg ) s l e e p ( rand ( ) % 4 + 1 ) ; pthread mutex lock (&part1 mutex ) ; part1++; p r i n t f ( Acquired new part1 %d\n, part1 ) ; pthread mutex unlock(&part1 mutex ) ; void a c q u i r e p a r t 2 f u n ( void arg ) s l e e p ( rand ( ) % 4 + 1 ) ; pthread mutex lock (&part2 mutex ) ; part2++; p r i n t f ( Acquired new part2 %d\n, part2 ) ; pthread mutex unlock(&part2 mutex ) ; void p r o d u c e i t e m fun ( void arg ) int produce ; produce = 1 ; s l e e p ( 2 ) ; pthread mutex lock (&part1 mutex ) ; i f (! part1 ) produce = 0 ; pthread mutex unlock(&part1 mutex ) ; pthread mutex lock (&part2 mutex ) ; i f (! part2 && produce ) produce = 0 ; 4
pthread mutex unlock(&part2 mutex ) ; i f ( produce ) pthread mutex lock (&part1 mutex ) ; part1 ; pthread mutex unlock(&part1 mutex ) ; pthread mutex lock (&part2 mutex ) ; part2 ; pthread mutex unlock(&part2 mutex ) ; pthread mutex lock (& storage mutex ) ; s t o r a g e ++; p r i n t f ( Produced new item %d\n, s t o r a g e ) ; pthread mutex unlock(& storage mutex ) ; void s e l l i t e m f u n ( void arg ) int n u m s e l l ; s l e e p ( rand ( ) % 10 + 1 ) ; pthread mutex lock (& storage mutex ) ; n u m s e l l = rand ( ) % 3 + 1 ; i f ( n u m s e l l > s t o r a g e ) n u m s e l l = s t o r a g e ; i f ( n u m s e l l ) s t o r a g e = s t o r a g e ; p r i n t f ( Sold %d item%c \n, num sell, n u m s ell > 1? s : ) ; pthread mutex unlock(& storage mutex ) ; char any key ; p t h r e a d t a c q u i r e p a r t 1 t h r e a d, a c q u i r e p a r t 2 t h r e a d ; p t h r e a d t produce item thread, s e l l i t e m t h r e a d ; p t h r e a d m u t e x i n i t (&part1 mutex, NULL) ; p t h r e a d m u t e x i n i t (&part2 mutex, NULL) ; p t h r e a d m u t e x i n i t (&storage mutex, NULL) ; s t a t u s = RUNNING; 5
p r i n t f ( Press ENTER to stop s i m u l a t i o n \n ) ; p t h r e a d c r e a t e (& a c q u i r e p a r t 1 t h r e a d, NULL, a c q u i r e p a r t 1 f u n, NULL) ; p t h r e a d c r e a t e (& a c q u i r e p a r t 2 t h r e a d, NULL, a c q u i r e p a r t 2 f u n, NULL) ; p t h r e a d c r e a t e (& produce item thread, NULL, produce item fun, NULL) ; p t h r e a d c r e a t e (& s e l l i t e m t h r e a d, NULL, s e l l i t e m f u n, NULL) ; s c a n f ( %c, &any key ) ; s t a t u s = SHUTDOWN; p t h r e a d j o i n ( a c q u i r e p a r t 1 t h r e a d, NULL) ; p t h r e a d j o i n ( a c q u i r e p a r t 2 t h r e a d, NULL) ; p t h r e a d j o i n ( produce item thread, NULL) ; p t h r e a d j o i n ( s e l l i t e m t h r e a d, NULL) ; pthread mutex destroy(&part1 mutex ) ; pthread mutex destroy(&part2 mutex ) ; pthread mutex destroy(& storage mutex ) ; 6