$B%^%k%A%9%l%C%I(B(1)

$BJBNsJ,;6%=%U%H%&%'%"(B

                                       $BEE;R!&>pJs9)3X7O(B
                                       $B?7>k(B $BLw(B
                                       <[email protected]>

$B$3$N%Z!<%8$O!"<!$N(B URL $B$K$"$j$^$9!#(B
http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08
$B$"$k$$$O!"<!$N%Z!<%8$+$i http://www.hlla.is.tsukuba.ac.jp/~yas/sie/
http://www.is.tsukuba.ac.jp/~yas/index-j.html
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html

$B"#%9%l%C%I!&%W%m%0%i%_%s%0(B

$B"!%9%l%C%I$H$O(B

$B%9%l%C%I(B(thread) $B$"$k$$$O!"(B $B7ZNL%W%m%;%9(B(lightweight processes) $B$H$O!"(B $B#1$D$NJ]8n$NC10L$H$7$F$N(B $B%W%m%;%9!J%?%9%/!$$"$k$$$O!$%"%I%l%96u4V!K(B $BFbIt$K$U$/$^$l$F$$$kO@M}E*$JJBNs=hM}$NC10L!#(B

$B%7%s%0%k%9%l%C%I$N%W%m%0%i%`(B
$B#1EY$K#1$D$N $B%^%k%A%9%l%C%I$N%W%m%0%i%`(B
$B#1EY$K%9%l%C%I$N?t$@$1$N

$B?^(B? $B%7%s%0%k%9%l%C%I$N%W%m%;%9$H%^%k%A%9%l%C%I$N%W%m%;%9(B

$B?^(B? $B%7%s%0%k%9%l%C%I$N%W%m%;%9$H%^%k%A%9%l%C%I$N%W%m%;%9(B

$B7ZNL%W%m%;%9$H$$$&$H!"FbIt$K%k!<%W$r4^$`$h$&$J8l46$,$"$k!#(B

$B"!%9%l%C%I$NMxMQL\E*(B

  • $BBP>N7?%^%k%A%W%m%;%C%5(B(SMP$B!"(BSymmetric Multiprocessor)$B$G$NJB(B $BNs=hM}!#IaDL$N%W%m%;%9$G$O=E$/$FJBNs=hM}$N8z2L$,=P$J$$!#(B
  • $B$b$H$b$HFbIt$KJBNs@-(B($BJB9T@-(B)$B$r4^$s$G$$$?%W%m%0%i%`$r<+A3$KI=8=$9$k$?$a!#(B CPU $B$,B.$/$J$C$?$N$G!"5v$5$l$k$h$&$K$J$C$?!#(B
    • $BJ,;6%7%9%F%`$GJ#?t$N%/%i%$%"%s%H$r07$&$h$&$J%5!<%P(B
    • fork() $B$d(B select() $B$r;H$&$h$&$J%W%m%0%i%`(B
    • $B%=%U%H%&%'%"3d9~$_!J%7%0%J%k!K$r;H$&$h$&$J%W%m%0%i%`(B
    • GUI $B%W%m%0%i%_%s%0(B
  • $BF~=PNOCY1d!"DL?.CY1d$N1#JC!#(B
  • $B%G%C%H%m%C%/2sHr!#(B

$B"!K\Ev$K%9%l%C%I$,I,MW$+(B

John K. Ousterhout, "Why Threads Are A Bad Idea (for most purposes)", Invited Talk at the 1996 USENIX Technical Conference (January 25, 1996). [PDF] [PowerPoint]

$B%^%k%A%9%l%C%I%W%m%0%i%_%s%0$O!"Hs>o$KFq$7$$!#(B

  • $B%W%m%0%i%_%s%0?M8}!#(BVisual Basic$B!"(BC$B!"(BC++$B!"(BThread
  • $BF14|!"%m%C%/$7$o$9$l!#%G%C%H%m%C%/!#(B
  • $B%G%P%C%0!#(B
  • $BJBNs2=$9$Y$F$->l=j$NH/8+!"D4@0!#(B
$B%7%s%0%k%9%l%C%I$N%$%Y%s%H6nF0$G=q$1$k$J$i!"$=$NJ}$,$$$$!#(B GUI$B!"J,;6$J$I!#(B

$B$I$3$G%9%l%C%I$r;H$&$Y$-$+!#(B

  • high-end servers (e.g. databases)
  • SMP $B$G$NJBNs=hM}!"(BCPU $B$,M_$7$$;~(B

$B"!%9%l%C%I$NFbMF(B

$B8D!9$N%9%l%C%I$4$H$K;}$D$b$N(B
  • $B%W%m%0%i%`%+%&%s%?(B
  • $B%9%?%C%/(B
  • $B%l%8%9%?(B
$B%W%m%;%9A4BN$G6&M-(B
  • $B%"%I%l%96u4V!"%a%b%j(B
  • $B%U%!%$%k5-=R;R(B
  • UID ($B%"%/%;%9@)8f(B)

$B"#(BPthread

Pthread $B$O!"(BPOSIX 1003.1c-1995$B$H$$$&I8=`$K=`5r$7$?%9%l%C%I!&%i%$%V%i%j!#(B POSIX Thread $B$H$b8F$P$l$k!#(B

$B"!(BPthread$B$rMxMQ$7$?%W%m%0%i%`$N%3%s%Q%$%k(B

Pthread $B$rMxMQ$7$?%W%m%0%i%`$r=q$/;~$K$O!"<!$N$h$&$J%X%C%@!&%U%!%$%k$r(B $BFI$_9~$`!#(B


#include <pthread.h>

Solaris (Unix International$B7O(B)$B$G$N%3%s%Q%$%k$H%j%s%/!#(B -D_REENTRANT$B$H(B-lpthread $B$rIU$1$k!#(B


----------------------------------------------------------------------
% cc -D_REENTRANT -o create create.c -lpthread [$B
% ./create [$B
...
% []
----------------------------------------------------------------------
$B%;%^%U%)$r;H$&;~!"(BSolaris 6 (SunOS 5.6, sakura) $B$G$O!"%j%s%/;~$K(B -lposix4 $B%*%W%7%g%s$rIU$1$k!#(BSolaris 7-9 (SunOS 5.7, 5.8, 5.9) $B$G$O!"%j%s%/;~$K(B -lrt $B%*%W%7%g%s$rIU$1$k!#(B

SGI (O2, Origin) $B$G$N%3%s%Q%$%k$H%j%s%/!#(B-lpthread $B$rIU$1$k!#(B


----------------------------------------------------------------------
% cc -o create create.c -lpthread [$B
% ./create [$B
...
% []
----------------------------------------------------------------------

$B"#%9%l%C%I$N@8@.!&>CLG(B

$B%9%l%C%I$O!"IaDL$N%W%m%0%i%`$N!"(B $B%5%V%k!<%A%s!J#C8@8l$N4X?t!"l9g!$8F$S=P$9$H!"8F$S=P$5$l$?J}$,F0$-!"<+J,<+?H$O!$;_$^(B $B$k!#%9%l%C%I$G$O!$?7$?$K%9%l%C%I$r@8@.$7$?>l9g!$@8@.$7$?J}$H@8@.$5(B $B$l$?J}$O!$O@M}E*$K$O#2$D$H$bF1;~$KF0$/!#(B

$B"#(Bfork-join$B%b%G%k(B

$B?^(B? fork-join$B%b%G%k$N<B8=(B

$B?^(B? fork-join$B%b%G%k$N

  1. $BC`<!=hM}!J%9%l%C%I!?%W%m%;%9$,#1$D!K$N>uBV$+$i;O$^$k(B
  2. $BJBNs@-$,I,MW$K$J$C$?;~!"(Bfork$BL?Na$GJ#?t$N%9%l%C%I!?%W%m%;%9$KJ,$+(B $B$l$FJBNs=hM}$r9T$&!#(B
  3. $BJBNs$KF0:n$G$-$kItJ,$,=*$k$H(B join $BL?Na$G:F$SC`<!=hM}$KLa$k!#(B

$B"!(BUnix$B$N(Bfork

fork() $B%7%9%F%`%3!<%k$G%3%T!<$,:n$i$l$k!#(B join $B$NBe$o$j$K!";R$I$b$O(B exit()$B!"?F$O(B wait()$B!#(B

$B"!(BPthread$B$O(Bcreate

Pthread $B$G$O!"%3%T!<$G$O$J$/(B create $B$G?7$?$K%9%l%C%I$r:n$k!#F1$84X?t$r(B $B@\(B call $B$9$k!#(B($BJL$N4X?t$r

$B8e$G(B join $B$9$kI,MW$,$J$$;~$K$O!"(Bpthread_detach() $B$r;H$C$F@Z$jN%$9!#(B (join$B$7$J$/$F$b%>%s%S$,;D$i$J$$!#(B)

$B"!%9%l%C%I$N@8@.$H(Bjoin


----------------------------------------------------------------------
   1: 
   2: /*
   3:         create-join-2.c -- $B%9%l%C%I$r#2$D:n$k%W%m%0%i%`(B
   4: */
   5: 
   6: #include <pthread.h>
   7: 
   8: void func1( int x );
   9: void func2( int x );
  10: 
  11: main()
  12: {
  13:     pthread_t t1 ;
  14:     pthread_t t2 ;
  15:         pthread_create( &t1, NULL, (void *)func1, (void *)10 );
  16:         pthread_create( &t2, NULL, (void *)func2, (void *)20 );
  17:         printf("main()\n");
  18:         pthread_join( t1, NULL );
  19:         pthread_join( t2, NULL );
  20: }
  21: 
  22: void func1( int x )
  23: {
  24:     int i ;
  25:         for( i = 0 ; i<3 ; i++ )
  26:         {
  27:             printf("func1( %d ): %d \n",x, i );
  28:         }
  29: }
  30: 
  31: void func2( int x )
  32: {
  33:     int i ;
  34:         for( i = 0 ; i<3 ; i++ )
  35:         {
  36:             printf("func2( %d ): %d \n",x, i );
  37:         }
  38: }
----------------------------------------------------------------------

$B

----------------------------------------------------------------------
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/create-join-2.c [$B
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/Makefile [$B
% make create-join-2 [$B
gcc -D_REENTRANT -g   -c create-join-2.c -o create-join-2.o
gcc -D_REENTRANT -g -o create-join-2 create-join-2.o -lpthread
% ./create-join-2  [$B
main()
func1( 10 ): 0 
func1( 10 ): 1 
func1( 10 ): 2 
func2( 20 ): 0 
func2( 20 ): 1 
func2( 20 ): 2 
% []
----------------------------------------------------------------------
$B$3$NNc$G$O!"<!$N#3$D$N%9%l%C%I$,:n$i$l$k!#(B
  1. main $B$r func2 $B$+$i:n$i$l$?%9%l%C%I(B t2
  2. func1 $B$+$i:n$i$l$?%9%l%C%I(B t1
$B%^%k%A%9%l%C%I!&%W%m%0%i%_%s%0$G$O!"(Bmain$B4X?t$b$^$?#1$D$N%9%l%C%I$,$B=i4|%9%l%C%I(B $B!"$"$k$$$O!"(B $B%a%$%s%9%l%C%I(B $B$H$h$V!#(BPthrad $B$G$O!"(B $B%a%$%s%9%l%C%I0J30$N%9%l%C%I$O!"(B pthread_create() $B$K$h$j:n$i$l$k!#(B

$B$I$&$$$&=g=x$G$BHsF14|E*(B(asynchronous) $B$J=hM}$rI=8=$9$k$?$a$N$b$N!#$I$&$7$F$bB>$N%9%l%C%I$HF14|$r9T$J$&I,MW$,(B $B=P$F$-$?;~$K$O!"(Bmutex $B$d>r7oJQ?t$H$$$C$?F14|5!G=$r;H$&!#(B

pthread_create()$B$G;XDj$5$l$?4X?t$+$i%j%?!<%s$9$k$H!"$=(B $B$N%9%l%C%I$,=*N;$9$k!#(Bpthread_exit() $B$r8F$S=P$7$F$b$h$$!#(B $B$?$@$7!"(B $B=i4|%9%l%C%I(B $B$,=*N;$9$k$H!"%W%m%;%9A4BN$,=*N;$9$k!#(B exit() $B%7%9%F%`%3!<%k$r8F$S=P$7$F$b=*N;$9$k!#(B

$B"#(Bmutex$B$K$h$k%9%l%C%I4V$NF14|(B

$B"!6&M-;q8;(B

$BJ#?t$N%W%m%;%9!?%9%l%C%I$G6&M-$7$J$1$l$P$J$i$J$$$b$N!#(B

$B%W%m%;%9$N>l9g!"%U%!%$%k!"C

$B

$B%9%l%C%I$N>l9g$O!"%W%m%0%i%_%s%08@8l$NJQ?t!#(B

$BJQ99$5$l$J$$JQ?t$NCM$rFI$`$@$1$J$i!"FC$KLdBj$O5/$-$J$$!#$=$l0U30$N;~!"(B $BFC$K!"J#?t$N%9%l%C%I$GCM$rFI$_=q$-$9$k;~$KLdBj$,5/$-$k!#(B

$B"!J#?t$N%9%l%C%I$K$h$k6&M-;q8;$N%"%/%;%9(B($B%m%C%/$J$7(B)


----------------------------------------------------------------------
   1: 
   2: /*
   3:  * mutex-nolock.c -- $B6&M-;q8;$r%m%C%/$J$7$G%"%/%;%9$9$k%W%m%0%i%`(B
   4:  */
   5: 
   6: #include <pthread.h>
   7: 
   8: void thread_A(), thread_B();
   9: int     shared_resource ;
  10: 
  11: main() {
  12:     pthread_t t1 ;
  13:     pthread_t t2 ;
  14:         shared_resource = 0 ;
  15:         pthread_setconcurrency( 2 );
  16:         pthread_create( &t1, NULL, (void *)thread_A, 0 );
  17:         pthread_create( &t2, NULL, (void *)thread_B, 0 );
  18:         pthread_join( t1, NULL );
  19:         pthread_join( t2, NULL );
  20:         printf("main(): shared_resource == %d\n", shared_resource );
  21: }
  22: 
  23: void thread_A()
  24: {
  25:     int i, x ;
  26:         for( i = 0 ; i<1000000 ; i++ )
  27:         {
  28:             x = shared_resource ;
  29:             x = x + 1 ;
  30:             shared_resource = x ;
  31:         }
  32: }
  33: 
  34: void thread_B() {
  35:     int i, x ;
  36:         for( i = 0 ; i<1000000 ; i++ ) {
  37:             x = shared_resource ;
  38:             x = x + 1 ;
  39:             shared_resource = x ;
  40:         }
  41: }
----------------------------------------------------------------------

pthread_setconcurrency() $B$O!"MxMQ$7$?$$(B CPU $B?t$r%7%9%F%`$KMW5a$9$k$b$N!#(B Solaris 6 (SunOS 5.6, sakura) $B$G$O!"(Bthr_setconcurrency() $B$r;H$&!#(B

$B"!

$B6&M-%a%b%j7?%^%k%A%W%m%;%C%5$G$N

----------------------------------------------------------------------
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/mutex-nolock.c [$B
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/Makefile [$B
% make mutex-nolock [$B
gcc -D_REENTRANT -g -mcpu=v8 -Dpthread_setconcurrency=thr_setconcurrency -Dpthread_getconcurrency=thr_getconcurrency   -c mutex-nolock.c -o mutex-nolock.o
gcc -D_REENTRANT mutex-nolock.o -lpthread -lposix4 -o mutex-nolock
% ./mutex-nolock [$B
main(): shared_resource == 1004100
% ./mutex-nolock [$B
main(): shared_resource == 1003470
% ./mutex-nolock [$B
main(): shared_resource == 1003316
% ./mutex-nolock [$B
main(): shared_resource == 1003143
%
----------------------------------------------------------------------
thread_A(), thread_B()$B$H#2$D$N%9%l%C%I$,:n(B $B$i$l$F$$$k!#@0?t7?$NJQ?t(B shared_resource $B$O!"$=$N#2$D$N(B $B%9%l%C%I$NN>J}$+$i%"%/%;%9$5$l$k!##2$D$N%9%l%C%I$G9g7W(B2000000 $BA}$($kM=(B $BDj$@$,!"$B"!9M;!(B($B%m%C%/$J$7(B)

$B$3$N%W%m%0%i%`$,6&M-%a%b%j7?%^%k%A%W%m%;%C%5$GF0$$$F$$$k$H$7$F!"F0$-$r(B $B9M$($F$($k!#(B


----------------------------------------------------------------------
thread_A()			thread_B()
	:				:
	:				:
28: x = shared_resource ;
				37: x = shared_resource ;
29: x = x + 1 ;
				38: x = x + 1 ;
30: shared_resource = x ;
				39: shared_resource = x ;
	:				:
	:				:
----------------------------------------------------------------------

shared_resource++$B$H=q$$$F$b$@$a!#J#?t$N5!3#8lL?Na$KJ,3d(B $B$5$l$k$N$G!#(B

$B"!Aj8_GS=|(B

$BAj8_GS=|(B(mutual exclusion)$B!'(B $B$"$k;q8;$r%"%/%;%9$G$-$k%9%l%C%I$N?t$r(B $BB?$/$F$b#1$D$K$9$k!#(B

$B%W%m%0%i%`$N;zLL>e!"Aj8_GS=|$,I,MW$JItJ,$r(B $B:]$I$$ItJ,(B(critical section) ( $B%/%j%F%#%+%k%;%/%7%g%s(B ) $B$H$$$&!#(B

$B"!(BPthread$B$G$NAj8_GS=|(B

Pthread $B$G$O!"Aj8_GS=|$r9T$J$&$?$a$K!"(B mutex $B$H$$$&;EAH$_$,$"$k!#<!$N$h$&$K$7$F!"Aj8_GS=|$r9T$J$$$?$$ItJ,$r(B lock $B$H(B unlock $B$G0O$`!#(B

    pthread_mutex_t mutex1 ;
	:
	:
    pthread_mutex_lock( &murex1 );
	$B!cAj8_GS=|$7$?$$ItJ,!J:]$I$$ItJ,!K!d(B
    pthread_mutex_unlock( &mutex1 );

$B"!J#?t$N%9%l%C%I$K$h$k6&M-;q8;$N%"%/%;%9(B($B%m%C%/IU$-(B)

$B%m%C%/$J$7(B$B$N%W%m%0%i%`$r!"(Bmutex $B$r;H$C(B $B$F=q$-D>$7$?$b$N!#(B

----------------------------------------------------------------------
   1: /*
   2:  * mutex-lock.c -- $B6&M-;q8;$r%m%C%/$7$J$,$i%"%/%;%9$9$k%W%m%0%i%`(B
   3:  */
   4: 
   5: #include <pthread.h>
   6: 
   7: void thread_A(), thread_B();
   8: int     shared_resource ;
   9: pthread_mutex_t mutex1 ;
  10: 
  11: main() {
  12:     pthread_t t1 ;
  13:     pthread_t t2 ;
  14:         shared_resource = 0 ;
  15:         pthread_mutex_init( &mutex1, NULL );
  16:         pthread_setconcurrency( 2 );
  17:         pthread_create( &t1, NULL, (void *)thread_A, 0 );
  18:         pthread_create( &t2, NULL, (void *)thread_B, 0 );
  19:         pthread_join( t1, NULL );
  20:         pthread_join( t2, NULL );
  21:         printf("main(): shared_resource == %d\n", shared_resource );
  22: }
  23: 
  24: void thread_A()
  25: {
  26:     int i, x ;
  27:         for( i = 0 ; i<1000000 ; i++ )
  28:         {
  29:             pthread_mutex_lock( &mutex1 );
  30:             x = shared_resource ;
  31:             x = x + 1 ;
  32:             shared_resource = x ;
  33:             pthread_mutex_unlock( &mutex1 );
  34:         }
  35: }
  36: 
  37: void thread_B() {
  38:     int i, x ;
  39:         for( i = 0 ; i<1000000 ; i++ ) {
  40:             pthread_mutex_lock( &mutex1 );
  41:             x = shared_resource ;
  42:             x = x + 1 ;
  43:             shared_resource = x ;
  44:             pthread_mutex_unlock( &mutex1 );
  45:         }
  46: }
----------------------------------------------------------------------

$B"!


----------------------------------------------------------------------
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/mutex-lock.c [$B
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/Makefile [$B
% make mutex-lock [$B
gcc -D_REENTRANT mutex-lock.o -lpthread -lposix4 -o mutex-lock
% ./mutex-lock  [$B
main(): shared_resource == 2000000
% ./mutex-lock [$B
main(): shared_resource == 2000000
% ./mutex-lock [$B
main(): shared_resource == 2000000
% []
----------------------------------------------------------------------

$B"!9M;!(B($B%m%C%/IU$-(B)

$B$3$N%W%m%0%i%`$,6&M-%a%b%j7?%^%k%A%W%m%;%C%5$GF0$$$F$$$k$H$7$F!"F0$-$r(B $B9M$($F$($k!#(B

----------------------------------------------------------------------
thread_A()				thread_B()

	:					:
29: pthread_mutex_lock( &mutex1 );		:
					40: pthread_mutex_lock( &mutex1 );
30: x = shared_resource ;		$B!cB>$N%9%l%C%I$,uBV$G$7$P$i$/BT$?$5$l$k!d(B
32: shared_resource = x ;			:
33: pthread_mutex_unlock( &mutex1 );		:
	:				$B!c


$B8e$+$iMh$?(B thread_B() $B$O!"B>$N%9%l%C%I$,

$B"#>r7oJQ?t$K$h$k%9%l%C%I4V$NF14|(B

$B%9%l%C%I$G%W%m%0%i%`$r:n$C$F$$$k$H!"$"$k%9%l%C%I$,JL$N%9%l%C%I$N;E;v$N(B $B40N;$rBT$DI,MW$,=P$,$"$k!#(B

$B"!%Q%$%W$H=[4D%P%C%U%!(B

Unix $B$N%Q%$%W$N$h$&$J$3$H$r%9%l%C%I$r;H$C$F

----------------------------------------------------------------------
thread_A | thread_B
----------------------------------------------------------------------
$B#2$D$N%9%l%C%I$N4V$K$O!"%P%C%U%!$rCV$/!#(B

$B?^(B? $B4D>u%P%C%U%!!CHq

$B?^(B? $B4D>u%P%C%U%!!"@8;:CHq

$B%P%C%U%!$,6u$N;~!"(Bthread_B() $B$O!"(Bthread_A() $B$,2?$+%G!<(B $B%?$r%P%C%U%!$KF~$l$k$N$rBT$D!#%P%C%U%!$,$$$C$Q$$$N;~!"(Bthread_A() $B$O!"(Bthread_B() $B$,%P%C%U%!$+$i2?$+%G!<%?$r$B"!>r7oJQ?t(B $B>r7oJQ?t(B(condition variable) $B$G!"$"$k>r7o$,@8$8$?$3$H$rBT$D!#(B

$B>r7oJQ?t$NA`:n!'(B

wait
$B$"$k>r7o$,K~$?$5$l$k$^$GBT$D(B
signal
$B$"$k>r7o$,K~$?$5$l$?$3$H$rEA$($k!#BT$C$F$$$k%9%l%C%I$,#1$D$@$15/$->e$,$k!#(B
broadcast
$B$"$k>r7o$,K~$?$5$l$?$3$H$rEA$($k!#BT$C$F$$$k%9%l%C%I$,A4$F5/$->e$,$k!#(B

$B"!>r7oJQ?t$r;H$C$?4D>u%P%C%U%!(B


----------------------------------------------------------------------
   1: 
   2: /*
   3:  * condv-buffer.c -- $B>r7oJQ?t$r;H$C$?4D>u%P%C%U%!(B
   4: */
   5: 
   6: #include <pthread.h>
   7: 
   8: void thread_A(), thread_B();
   9: 
  10: #define BUFFER_SIZE     4               /* $B%P%C%U%!$NBg$-$5(B */
  11: struct circular_buffer
  12: {
  13:         int rp ;                        /* $BFI$_=P$90LCV(B */
  14:         int wp ;                        /* $B=q$-9~$`0LCV(B */
  15:         int used ;                      /* $B%P%C%U%!Fb$NMWAG?t(B */
  16:         int data[BUFFER_SIZE];          /* $B%G!<%?$rJ]B8$9$k>l=j(B */
  17:         pthread_mutex_t mutex ;         /* $B$3$N9=B$BN$NAj8_GS=|$N$?$a$N(B mutex */
  18:         pthread_cond_t  not_full ;      /* $B%P%C%U%!$,0lGU$G$O$J$$>uBV$rBT$D$?$a$N>r7oJQ?t(B */
  19:         pthread_cond_t  not_empty ;     /* $B%P%C%U%!$,6u$G$O$J$$>uBV$rBT$D$?$a$N>r7oJQ?t(B */
  20: };
  21: 
  22: void put( struct circular_buffer *b,int x )
  23: {
  24:         pthread_mutex_lock( &b->mutex );
  25: loop:   if( b->used == BUFFER_SIZE )
  26:         {
  27:             pthread_cond_wait( &b->not_full,&b->mutex );
  28:             goto loop;
  29:         }
  30:         b->data[ b->wp++ ] = x ;
  31:         if( b->wp >= BUFFER_SIZE )
  32:             b->wp = 0 ;
  33:         b->used ++ ;
  34:         pthread_cond_signal( &b->not_empty );
  35:         pthread_mutex_unlock( &b->mutex );
  36: }
  37: 
  38: int get( struct circular_buffer *b )
  39: {
  40:     int x ;
  41:         pthread_mutex_lock( &b->mutex );
  42: loop:   if( b->used == 0 )
  43:         {
  44:             pthread_cond_wait( &b->not_empty,&b->mutex );
  45:             goto loop;
  46:         }
  47:         x = b->data[ b->rp++ ] ;
  48:         if( b->rp >= BUFFER_SIZE )
  49:             b->rp = 0 ;
  50:         b->used -- ;
  51:         pthread_cond_signal( &b->not_full );
  52:         pthread_mutex_unlock( &b->mutex );
  53:         return( x );
  54: }
  55: 
  56: main()
  57: {
  58:     pthread_t t1 ;
  59:     pthread_t t2 ;
  60:     struct circular_buffer *b  ;
  61:         b = (struct circular_buffer *)malloc(sizeof(struct circular_buffer));
  62:         if( b == NULL )
  63:         {
  64:             perror("no memory for struct buffer\n");
  65:             exit( -1 );
  66:         }
  67:         b->rp = 0 ;
  68:         b->wp = 0 ;
  69:         b->used = 0 ;
  70:         pthread_mutex_init( &b->mutex, NULL );
  71:         pthread_cond_init( &b->not_full,NULL );
  72:         pthread_cond_init( &b->not_empty,NULL );
  73:         pthread_setconcurrency( 2 );
  74:         pthread_create( &t1, NULL, (void *)thread_A, (void *)b );
  75:         pthread_create( &t2, NULL, (void *)thread_B, (void *)b );
  76:         pthread_join( t1, NULL );
  77:         pthread_join( t2, NULL );
  78: }
  79: 
  80: void thread_A( struct circular_buffer *b )      /* producer */
  81: {
  82:     int i,x ;
  83:         for( i = 0 ; i<10 ; i++ )
  84:         {
  85:             x = i ;
  86:             printf("thread_A(): put( %d )\n",x );
  87:             put( b,x );
  88:         }
  89: }
  90: 
  91: void thread_B( struct circular_buffer *b )      /* consumer */
  92: {
  93:     int i, x ;
  94:         for( i = 0 ; i<10 ; i++ )
  95:         {
  96:             x = get( b );
  97:             printf("thread_B(): get() %d.\n", x );
  98:         }
  99: }
----------------------------------------------------------------------

put() $B$O!"%P%C%U%!$K%G!<%?$rDI2C$9$k;~$K;H$&

$B4pK\E*$K$O!"F~8}$G(B pthread_mutex_lock() $B$7!"(B $B=P8}$G(B pthread_mutex_unlock() $B$9$k!#(B

$B%P%C%U%!$,0lGU$N;~$K$O!">r7oJQ?t(Bb->not_full $B$G!"(B $B0lGU$G$J$$$H$$$&>r7o$K$J$k$^$GBT$D!#(B

$BBT$C$F$$$k4V$O!"(Bmutex $B$N%m%C%/$O2r=|$5$l$k!#(B

pthread_cond_wait() $B$+$i%j%?!<%s$7$FMh$k;~$K$O!"$b$&0lEY(B $B%m%C%/$5$l$?>uBV$KLa$k$,!"BT$C$F$$$k4V$K!"B>$NJQ?t(B (rp,wp,data)$B$,=q$-49$($i$l$F$$$k2DG=@-$,$"$k$N$G!"$b$&0l(B $BEY:G=i$+$iD4$Y$k!#(B

get() $B$O!"%P%C%U%!$+$i%G!<%?$rput()$B$H$[$\BP>N7A!#%P%C%U%!$,6u$N;~$K!"(Bwait $B$7!"%P%C%U%!$,$b$O$d0lGU$G$O$J$$$3$H$r(Bsignal $B$9$k!#(B

thread_A() $B$O!"#1#02s%P%C%U%!$K%G!<%?$r=q$-9~$`%9%l%C%I!#(B thread_B() $B$O5U$K!"#1#02s%P%C%U%!$+$i%G!<%?$rFI$_=P$9%9(B $B%l%C%I!#(B

$B"!


----------------------------------------------------------------------
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/condv-buffer.c [$B
% wget http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2003/2004-01-08/ex/Makefile [$B
% make condv-buffer [$B
gcc -D_REENTRANT -g -mcpu=v8 -Dpthread_setconcurrency=thr_setconcurrency -Dpthread_getconcurrency=thr_getconcurrency   -c condv-buffer.c -o condv-buffer.o
gcc -D_REENTRANT condv-buffer.o -lpthread -lposix4 -o condv-buffer
% ./condv-buffer  [$B
thread_A(): put( 0 )
thread_A(): put( 1 )
thread_A(): put( 2 )
thread_A(): put( 3 )
thread_A(): put( 4 )
thread_A(): put( 5 )
thread_B(): get() 0.
thread_B(): get() 1.
thread_B(): get() 2.
thread_B(): get() 3.
thread_B(): get() 4.
thread_A(): put( 6 )
thread_A(): put( 7 )
thread_A(): put( 8 )
thread_A(): put( 9 )
thread_B(): get() 5.
thread_B(): get() 6.
thread_B(): get() 7.
thread_B(): get() 8.
thread_B(): get() 9.
% []
----------------------------------------------------------------------
$BJ#?t$N%9%l%C%I$,F1;~$KF0$$$F$$$k!#%P%C%U%!$K$?$a$i$l$k$N$O!":GBg(B4$B$J$N(B $B$K!"(Bput() $B$,(B 5 $B2sO"[email protected]$7$F$$$k$h$&$K8+$($k!#(Bprintf() $B$N=gHV$H(B put(), get() $B$N=gHV$O0c$&$3$H$,$"$k!#(B

$B"!%@%V%k%P%C%U%!%j%s%0(B

$B@0?t$r#1$D%P%C%U%!$K=q$-9~$`$@$1$G%m%C%/!?%"%s%m%C%/$r9T$J$C$F$$$k$H!"(B $B$B"!(Bsignal$B$+(Bbroadcast$B$+(B

$B%P%C%U%!$KMWAG$r!V#1$D$:$D!WDI2C$7$F$$$k$N$G!"(B pthread_cond_signal() $B$G$b$h$$!#(B pthread_cond_broadcast() $B$KJQ$($F$bF0$/$h$&$K%W%m%0%i%`$r(B $B:n$k!#(B

pthread_cond_wait() $B$GBT$C$F$$$k4V$K>r7o$,JQ$o$C$F$$$k$+$b$7$l$J$$$N$G!"(B $B:G=i$+$iD4$YD>$9!#(Bsignal $B$G#1?M$@$1$7$+5/$->e$,$i$J$$$H2>Dj$7$F$O$$$1(B $B$J$$!#(B

$B!V#1$D$:$D!W$G$O$J$/!"J#?t8DF1;~$KFI$_=q$-$9$k;~$K$O!"(B pthread_cond_broadcast() $B$G$J$$$H$@$a!#(B

$BLB$C$?;~$K$O!"(Bpthread_cond_broadcast()$B!#(B

$B"#%9%l%C%I$H%a%b%j(B

$B"!(BPthread$B$N%a%b%j%b%G%k(B

$B0l
  • pthread_create() $B$N;~E@$G?F%9%l%C%I$G9T$o$l$?=q9~$_$O!"(B $B;R%9%l%C%I$G8+$($k!#(B
  • pthread_mutex_unlock() $B$+!"(Bpthread_cond_wait() $B$G(B mutex $B$r2rJ|$7(B $B$?;~$K$=$N%9%l%C%I$G=q9~$s$@$b$N$O!"F1$8(B mutex $B$r(B lock $B$9$k!"B>$N%9%l%C(B $B%I$GFI$a$k!#(B
  • $B;R%9%l%C%I$,=*N;$7$?;~$K=q9~$s$@$b$N$O!"(Bpthread_join()$B$7$?;~$K?F(B $B%9%l%C%I$GFI$a$k!#(B
  • pthread_cond_signal() $B$+(Bpthread_cond_broadcast() $B$9$k%9%l%C%I$,=q(B $B9~$s$@$b$N$O!"$=$l$G5/$-$k%9%l%C%I$GFI$a$k!#(B $BF14|$r;H$($PLdBj$,$J$$$,!"F14|$r$H$C$F$$$J$$$H2?$,5/$-$k$+M=A[$G$-$J$$!#(B

    $B"!(Bauto$BJQ?t(B

    $B3F%9%l%C%I$K$O!"FHN)$7$?%9%?%C%/$,3d$jEv$F$i$l$k!##C8@8l$N(B auto $BJQ?t$O!"(B $B%9%l%C%I$4$H$K%3%T!<$,:n$i$l$k!#(B

    $B!c!]!d:F5"8F=P$7(B

    $B%9%l%C%I4V$G%]%$%s%?$rEO$9;~$K$O!"%9%l%C%I$N$B"!(Bstatic$BJQ?t(B

    $B%7%s%0%k%9%l%C%I$N%W%m%0%i%`$G$O!"(Bstatic$BJQ?t$O!"%W%m%0%i%`$N%b%8%e!<%k@-(B $B$r9b$a$k$?$a$KM-8z$K;H$o$l$F$-$?!#(B

    $B%^%k%A%9%l%C%I$HAj@-$,Hs>o$K0-$$!#(Bstatic$BJQ?t$b(Bextern$BJQ?t$HF1MM$KJ#?t$N(B $B%9%l%C%I$G6&M-$5$l$k!#JQ99$9$k>l9g$K$O!"(Bmutex $B$G%m%C%/$,I,MW$K$J$k!#(B

    $B"!(Bstatic$BJQ?t$r;H$C$?%i%$%V%i%j4X?t(B

    TCP/IP $B$G%W%m%0%i%`$r=q$/;~$K;H$&(B gethostbyname() $B$O!"(B static$BJQ?t$KCM$r%;%C%H$7$F!"%j%?!<%s!&%P%j%e!<$H$7$FJV$7$F$k!#(B
    
    ----------------------------------------------------------------------
    struct hostent *gethostbyname( char *name ){
        static struct hostent ret ;
    	.....
    	return( &ret );
    }
    ----------------------------------------------------------------------
    
    
    $BJ#?t$N%9%l%C%I$,F1;~$K$3$N4X?t$r8F$S=P$7$?>l9g!"F1$8(Bstatic$BJQ?t$,;H$o$l(B $B$k!#(B

    $B"!%9%l%C%I!&%;!<%U(B

    $BJ#?t$N%9%l%C%I$G8F$S=P$7$F$b$-$A$s$HF0:n$9$k$3$H$r!"(B $B%9%l%C%I!&%;!<%U(B(thread-safe) $B$H$$$&!#(B MT-Safe(multi-thread-safe) $B$d(B $B:FF~2DG=(B(reentrant) $B$H$$$&$3$H$b$"$k!#(B

    extern$B$d(Bstatic$B$r;H$o$:!"(Bauto$BJQ?t$d(Bmalloc()$B$@$1$r;H$C$F$$$k$h$&$J

    $BJL$N%9%l%C%I!&%;!<%U$G$J$$

    $B"!%9%l%C%I!&%;!<%U$J%$%s%?%U%'!<%9(B

    $B%9%l%C%I!&%;!<%U$K$J$k$h$&$K$9$k$K$O!"%$%s%?%U%'!<%9$rJQ99$9$kI,MW$,$"(B $B$k!#(B
    Sun $B$N%^%K%e%"%k$h$j(B:
    ----------------------------------------------------------------------
    struct hostent *gethostbyname(const char *name);
    
    struct hostent *gethostbyname_r(const char *name,
         struct hostent *result, char *buffer, int buflen,
         int *h_errnop);
    
    ----------------------------------------------------------------------
    
    O2$B$K$O!"(Bgethostbyname_r() $B$O$J$$!#(B

    $B"!%9%l%C%I!&%;!<%U$G$O$J$$

    • $B#1$D$N%9%l%C%I$@$1$+$i$7$+8F$S=P$5$J$$$h$&$K$9$k!#(B
    • $B%m%C%/$r;H$&!#(B
    $B0l8+L54X78$Nl9g$,$"$k!#(B

    $B"#(BPthread$B$G$N%;%^%U%)$NMxMQ(B

    Pthread $B$K$O!"

    $B<!$N$h$&$J4X?t$,MxMQ2DG=$G$"$k!#(B

    
    #include <semaphore.h>
    
    
    int sem_init(sem_t *sem, int pshared, unsigned int value)
    $B=i4|2=!#(Bpshared$B$,(B0$B$@$H%W%m%;%9Fb$GM-8z!#(Bvalue$B$O=i4|CM!#(B
    int sem_wait(sem_t * sem)
    P$BL?Na!#CM$r8:$i$9!#(B0$B$N>l9g$O;_$^$k!#(B
    int sem_trywait(sem_t * sem)
    $BHs%V%m%C%/$N(Bsem_wait()$B!#(B0$B$G$b;_$^$i$:%(%i!<$rJV$9!#(B
    int sem_post(sem_t * sem)
    V$BL?Na!#CM$rA}$d$9!#(B
    int sem_getvalue(sem_t * sem, int * sval)
    $B8=:_$NCM$rJV$9!#IaDL$OLr$K$ON)$?$J$$!#<!$N=V4V$K$OB>$N%9%l%C%I$,(BP/V$B$7$F$$$k$+$b$7$l$J$$$N$G!#(B
    int sem_destroy(sem_t * sem)
    $B%;%^%U%)$rGK4~$9$k!#(B
    $BCm0U!'(B SystemV $BM3Mh$N%;%^%U%)(B(semget(),semop(),semctl())$B$H$O0c$&!#(B

    $BCm0U!'L>A0IU$-$N%;%^%U%)$b$"$k!#(Bsem_open() $B$G:n@.!?=i4|2=$7!"(B sem_unlink() $B$G:o=|$9$k!#(B

    $BCm0U!'(BSolaris $B$K$O!"(BPOSIX $B$N%;%^%U%)$H$OJL$K!"%+!<%M%kFb$G$N%G%P%$%9!&(B $B%I%i%$%P:n@.$N$?$a$N%;%^%U%)$,MQ0U$5$l$F$$$k!#(B

    $B"#(BJava$B$N%9%l%C%I(B

    Java $B$K$O!":G=i$+$i8@8l$N%l%Y%k$G%9%l%C%I$N5!G=$,F~$C$F$$$k!#(B

    ----------------------------------------------------------------------
    Java			Pthread
    ----------------------------------------------------------------------
    new Thread(); start();	pthread_create()
    join()			pthread_join()
    synchronized		pthread_mutex_lock()$B$H(Bpthread_mutex_unlock()$B$NAH(B
    wait()			pthread_cond_wait()
    wait(long timeout)	pthread_cond_timedwait()
    notify()		pthread_cond_signal()
    notifyAll()		pthread_cond_broadcast()
    ----------------------------------------------------------------------
    

    Java $B$N(B synchronized $B$O!":F5"2DG=!#(BPTHREAD_MUTEX_RECURSIVE $BAjEv!#(B $B#1$D$N%9%l%C%I$,#2EYF1$8%*%V%8%'%/%H$r%m%C%/$7$F$b$h$$!#(B

    Pthreads $B$N%W%m%0%i%`$G!"#1$D$N(B mutex $B$H#1$D$N>r7oJQ?t$r;H$C$?$b$N$J$i!"(B Java $B$G4JC1$K=q$-D>$;$k!#(B

    $B=[4D%P%C%U%!$N%W%m%0%i%`(B$B$O!"#1$D$N(B mutex $B$G#2$D$N>r7oJQ?t$r;H$C$F$$$k$N$G!"C1=c$K$O(B Java $B$G=q$-D>$;$J$$!#(B $B@8;:CHq

    Java $B$G=q$+$l$?%9%l%C%I$N%W%m%0%i%`$O!"1x$$$b$N$,$1$C$3$&$"$k!#%9%l%C(B $B%I!V4V!W$NF14|$G!"BP>N7O$K$J$k$Y$-=j$r!"JRJ}$N%9%l%C%I$N%a%=%C%I$K$7$F!"(B $BHsBP>N$K$J$C$F$$$k$3$H$,$"$k!#(BJava $B$G%W%m%0%i%`$r=q$/;~$K$b!"(Bactive object (thread) $B$H(B passive object (thread$B$J$7(B)$B$r$-$A$s$HJ,$1$?J}$,$h$$!#(B

    $B"!(BJava$B$N%a%b%j%b%G%k(B

    $B%9%l%C%IFb$OC`<!$HF1$8$@$,!"%9%l%C%I4V$O(B volatile $B$r=|$$$F2?$,$*$-$k$+(B $B$o$+$i$J$$!#(B

    long $B$H(B double $B0J30$N7?$O!"86;OE*!#(B volatile long, volatle double $B$O86;OE*!#(B

    $B0l

  • $B$"$k%9%l%C%I$,=q9~$_!"%m%C%/$r2rJ|$7$?8e(B(synchronized$B$rH4$1$?8e(B)$B!"(B $BJL$N%9%l%C%I$,F1$8%m%C%/$r3NJ]$7$?8e(B(synchronized $B$NCf(B)$B$G!"FI$a$k!#(B
  • $B%9%l%C%I$,(B volatile $B$N%U%#!<%k%I$X=q9~$s$@>l9g!"(B $B<!$N%a%b%j$X$NA`:n$NA0$K%a%b%j$K=q$+$l$k!#(B volatile $B$N%U%#!<%k%I$rFI9~$`%9%l%C%I$O!"(B $B%-%c%C%7%e$+$i$G$O$J$/I,$:%a%b%j$+$iFI$`!#(B
  • $B%9%l%C%I$,%*%V%8%'%/%H$N%U%#!<%k%I$K!V:G=i$K!W%"%/%;%9$9$k;~!"(B $B=i4|CM$+B>$N%9%l%C%I$K$h$C$F=q9~$^$l$?CM$,FI$a$k!#(B $B!JJQ$JCM$O8+$($J$$!#!K(B
  • $B%9%l%C%I$,=*N;$9$k;~!"(B $BA4$F$N=q9~$_$O%a%b%j$KH?1G$5$l$k!#(B Thread.join() $B$GF14|$r$H$l$P!"(B $B=*N;$7$?%9%l%C%I$N=q9~$_$,A4$F8+$($k!#(B $BF14|$r;H$($PLdBj$,$J$$$,!"F14|$r$H$C$F$$$J$$$H2?$,5/$-$k$+M=A[$G$-$J$$!#(B

    $B"!>r7oJQ?t$r;H$C$?4D>u%P%C%U%!(B(Java)

    
    ----------------------------------------------------------------------
       1: 
       2: /*
       3:  * CircularBuffer.java -- Java $B$K$h$k4D>u%P%C%U%!(B
       4: */
       5: 
       6: class CircularBuffer
       7: {
       8:     static final int BUFFER_SIZE = 4 ;
       9:     int rp ;            // $BFI$_=P$90LCV(B
      10:     int wp ;            // $B=q$-9~$`0LCV(B
      11:     int data[];         // $B%G!<%?$rJ]B8$9$k>l=j(B
      12:     int used ;          // $B%P%C%U%!Fb$NMWAG?t(B
      13:     CircularBuffer()
      14:     {
      15:         data = new int[BUFFER_SIZE];
      16:         rp = 0 ;
      17:         wp = 0 ;
      18:     }
      19: 
      20:     public synchronized void put( int x ) throws InterruptedException
      21:     {
      22:         while( used == data.length )
      23:             wait();
      24:         data[ wp++ ] = x ;
      25:         if( wp == data.length )
      26:             wp = 0 ;
      27:         if( used++ == 0 )
      28:             notifyAll();
      29:     }
      30: 
      31:     public synchronized int get() throws InterruptedException
      32:     {
      33:         int x ;
      34:         while( used == 0 )
      35:             wait();         
      36:         x = data[ rp++ ] ;
      37:         if( rp >= data.length )
      38:             rp = 0 ;
      39:         if( used-- == data.length )
      40:             notifyAll();
      41:         return( x );
      42:     }
      43: 
      44:     static void thread_A( CircularBuffer b )    // Producer
      45:     {                           
      46:         int i,x ;
      47:         try {
      48:             for( i = 0 ; i<10 ; i++ )
      49:             {
      50:                 x = i ;
      51:                 System.out.println("thread_A(): put( "+x+" )");
      52:                 b.put( x );
      53:             }
      54:         }
      55:         catch( InterruptedException e )
      56:         {
      57:             System.err.println("thread_A(): Interrupted");
      58:         }
      59:     }
      60: 
      61:     static void thread_B( CircularBuffer b )    // Consumer
      62:     {
      63:         int i, x ;
      64:         try {
      65:             for( i = 0 ; i<10 ; i++ )
      66:             {
      67:                 x = b.get();
      68:                 System.out.println("thread_B(): get() "+x+".");
      69:             }
      70:         }
      71:         catch( InterruptedException e )
      72:         {
      73:             System.err.println("thread_B(): Interrupted");
      74:         }
      75:     }
      76: 
      77:     static void main(String argv[])
      78:     {
      79:         final CircularBuffer b = new CircularBuffer();
      80:         Thread t1 = new Thread( new Runnable()
      81:                                  { public void run() {thread_A(b);} } );
      82:         t1.start();
      83:         Thread t2 = new Thread( new Runnable()
      84:                                  { public void run() {thread_B(b);} } );
      85:         t2.start();
      86:         try {
      87:             t1.join();
      88:             t2.join();
      89:         }
      90:         catch( InterruptedException e )
      91:         {
      92:             System.err.println("main(): Interrupted");
      93:         }
      94:     }
      95: }
    ----------------------------------------------------------------------
    
    

    $B"#N}=,LdBj(B

    $B!z%9%l%C%I$N?t(B

    $BAj8_GS=|$N%W%m%0%i%`$d>r7oJQ?t%W%m%0%i%`$G%9%l%C%I$N?t$rA}$d$7$F$_$J$5$$!#(B

    $B!z

    $B#1$D$N$B!z%@%V%k%P%C%U%!%j%s%0(B $B=[4D%P%C%U%!$N%W%m%0%i%`(B$B$r(B $B%@%V%k%P%C%U%!%j%s%0(B$B$r9T$J$&%W%m%0%i%`$K(B $BJQ99$7$J$5$$!#(B

    $B!z>r7oJQ?t$N:o8:(B

    $B=[4D%P%C%U%!$N%W%m%0%i%`(B$B$G!">r7oJQ?t$r#1$D$K$J$k$h$&$KJQ99$7$J$5$$!#(B
  • $B0lEY$K(B wait $B$9$kI,MW$,$"$k$N$O!"(Bput() $BB&$+(B get() $B$N$I$A$i$+0lJ}$@$1$G$"$k!#(B $B$h$C$F!"N>J}$H$bF1$8%-%e!<$K$D$J$$$G$b!"F0:n$9$k!#(B

    $B"#2]Bj(B

    $B<!$N2]Bj$+$i#1$D$rA*$s$GDs=P$7$J$5$$!#LdBj$rFq$7$$J}$KJQ$($F$b$h$$!#Dy(B $B$a@Z$j$O!"(B2004$BG/(B1$B7n(B/14 ($B?eMKF|(B) 18:00 $B$H$9$k!#(B(23:59:59 $B$G$O$J$$(B)$B!#(B

    $B%l%]!<%H$O!"<!$N$h$&$J7A<0$NEE;R%a!<%k$GAw$k$3$H!#(B

    ----------------------------------------------------------------------
    To: [email protected]
    Subject: [pdsoft/report-thread-1] $B!cFbMF$K4X$7$?%5%V%8%'%/%H!d(B
    
    $B3X@RHV9f(B 200301234 ($B3F<+$N3X@RHV9f$GCV$-49$($k(B)
    $BL>A0(B $B4A;z$NL>A0(B
    
    $B!cK\J8!d(B
    ----------------------------------------------------------------------
    
    $B!cFbMF!d(B
    
    

    $BCm0U!'(Bsakura $B$N?7>k$N%m%0%$%sL>$O!"(Byshinjo $B$G$"$k!#(B $B%l%]!<%H$O!"([email protected] $B$KAw$k$3$H!#(B Subject: $B$K$O!"(Bpdsoft $B$H$$$&J8;z$H%l%]!<%H$NHV9f(B(report-thread-1)$B$rI,(B $B$:4^$a$J$5$$!#(B

    $BEE;R%a!<%k$NK\J8$N@hF,$K3X@RHV9f$HL>A0!J4A;z$NL>A0$,$"$k?M$O!"4A;z$G!K(B $B$r=q$-$J$5$$!#(B

    $BFbMF$O!"J8K!E*$K@5$7$$!"F|K\8l!"$^$?$O1Q8l$G=q$/$3$H!#J8>O$K$O!"=R8l$r(B $BIU$1$k!#BN8@;_$a$O!";H$C$F$O$$$1$J$$!#C1$K%W%m%0%i%`$r4^$a$k$N$G$O$J$/!"(B $B!V0J2<$K!{!{$N%W%m%0%i%`$r<($9!W$H=q$/!#

    $BAw$i$l$?%l%]!<%H$K$O!":G=i$NDy@Z$j0J9_$K$^$H$a$F3NG'1~Ez(B(acknowledge) $B$rJV$9!#%a%C%;!<%8$NJ6<:!"%/%i%C%7%eEy$KBP1~$9$k$?$a$K!";~4V@Z$l$K$h$k(B $B:FAw$J$I$N%j%+%P%j$OE,59$d$k$3$H!#(B

    $BAw$C$?%l%]!<%H$O!"9V5A$,=*$k$^$GJ]B8$7$J$5$$!#(B

    $B!z69$$66(B

    $B#1EY$K#1J}8~$Ne$KF1;~$K#3Bf$N

    
    vehicle(int direction)
    {
    	arrive_bridge( direction );
    	cross_bridge( direction );
    	exit_bridge( direction );
    }
    
    
    
    $B$3$N%3!<%I$G(B direction $B$O!"(B0 $B$^$?$O(B 1 $B$G$"$j!"66$N$I$NJ}8~$Karrive_bridge() $B$H(B exit_bridge() $B$r!"(Bmutex $B$H>r7o(B $BJQ?t$r;H$C$F=q$-$J$5$$!#(Barrive_bridge() $B$O!"0BA4$K$=$NJ}8~$GWFM$7$?$j!"=ENL%*!<%P!<$G66$,Mn$A(B $B$?$j$9$k$3$H$,$J$$$h$&$K$7$J$1$l$P$J$i$J$$!#%G%P%C%0$N$?$a$N%a%C%;!<%8(B $B$rE,592hLL$K=PNO$9$k!#(Bexit_bridge() $B$O!"66$rEO$j=*$($3$H$r9p$2(B $B$k$?$a$K8F$P$l$k!#$3$N;~!"2DG=$J$i$P!"BT$C$F$$$karrive_bridge() $B$+$i%j%?!<%s$5$;$k(B)$B!#(B

    $B$3$3$G$O!"8xJ?@-$OuBV$K$J$i$J$$$3$H$rJ](B $B>Z$7$J$/$F$b$h$$!#(B

    $B40@.$7$?%W%m%0%i%`$K$*$$$F!"?7$7$$l9g!"?7$7$$

    $B!z2=3XH?1~(B

    $B;@AG86;R$H?eAG86;R$+$i?e$,:n$i$l$kH?1~$r!"%9%l%C%I$r;H$C$F=q$-$J$5$$!#(B
    • $B?eAG86;R$b;@AG86;R$b?eJ,;R$b!"$=$l$>$l#1$D$N%9%l%C%I$G $B3F86;R$O!"$=$l$>$lJ#?t8D$"$k!#?eAG86;R$,#28D!";@AG86;R$,#18D$@$1$H$O8B$i$J$$!#?eAG$,#1#0#08D!";@AG$,#58D$H$$$&$h$&$J$3$H$b$"$jF@$k!#(B

    • $B?eAG86;R$O!"H?1~2DG=$K$J$k$H(B H_Ready() $B $B;@AG86;R$O!"H?1~2DG=$K$J$k$H(B O_Ready() $B $B>/$J$/$H$b#2$D$N?eAG86;R$H#1$D$N;@AG86;R$,$=$m$&$^$G!"(BH_Ready() $B$b(B O_Ready() $B$b!"%j%?!<%s$7$J$$!#(B
    • $B#3$D$N%9%l%C%I$N$&$A!"#1$D$N%9%l%C%I$,(B make_water() $B $B$3$N$h$&$Jr7oJQ?t!"$^$?$O!"%;%^%U%)$r;H$C$F=q$-$J$5$$!#(B

    $B?eAG86;R$d;@AG86;R$G$O$J$/!"?eAGJ,;R(B (H2)$B$d;@AGJ,;R(B (O2)$B$r;H$C$F$b$h$$!#(B

    
    
    pthread_create( ..., NULL, (void *)H_func, ... );
    pthread_create( ..., NULL, (void *)H_func, ... );
    pthread_create( ..., NULL, (void *)H_func, ... );
    pthread_create( ..., NULL, (void *)H_func, ... );
    pthread_create( ..., NULL, (void *)O_func, ... );
    pthread_create( ..., NULL, (void *)O_func, ... );
    pthread_create( ..., NULL, (void *)O_func, ... );
    
    H_func( ... )
    {
        printf(...);
        H_Ready(...);
    }
    
    O_func( ... )
    {
        printf(...);
        O_Ready(...);
    }
    
    H2O_func( ... )
    {
        printf(...);
    }
    
    H_Ready(...)
    {
        ....
    }
    
    O_Ready(...)
    {
        ....
    }
    
    make_water()
    {
        pthread_create( ..., NULL, (void *)H2O_func, ... );
    }
    
    
    

    $B!z=[4D%P%C%U%!$r%;%^%U%)$G

    $B=[4D%P%C%U%!$N%W%m%0%i%`$r!"%;%^%U%)$r;H$C$F=q$-D>$7$J$5$$!#(B

    $B%;%^%U%)$r;H$C$?=[4D%P%C%U%!$N%W%m%0%i%`$N:n@.$O!"<!$N652J=q$NN}=,Ld(B $BBj$K$b$J$C$F$$$k!#(B

    $B@6?e8,B?O:(B: "$B%*%Z%l!<%F%#%s%0%7%9%F%`(B",$B4dGH=qE9(B (1992). ISBN: 4000078526.


    $B",(B[$B$b$I$k(B] $B"+(B[12$B7n(B25$BF|(B] $B!&(B[1$B7n(B8$BF|(B] $B"*(B[1$B7n(B15$BF|(B]
    Last updated: 2004/01/08 03:16:06
    Yasushi Shinjo / <[email protected]>