📄 进程和线程编程.htm
字号:
<CENTER><A
href="http://www.huihoo.com/joyfire.net/11.html#Content">[目录]</A></CENTER>
<HR>
<BR><A id=I261 name=I261></A>
<CENTER><B><FONT
size=+2>线程同步</FONT></B></CENTER><BR>POSIX提供两种线程同步的方法,mutex和条件变量。mutex是一种简单的加锁的方法来控制对共享资源的存取。我们可以创建一个读/写程序,它们共用一个共享缓冲区,使用mutex来控制对缓冲区的存取。<BR>void
reader_function(void);<BR>void writer_function(void);<BR>char buf f e r ;<BR>int
buffer_has_item = 0;<BR>pthread_mutex_t mutex;<BR>struct timespec
delay;<BR>main( )<BR>{<BR>pthread_t reader;<BR>delay.tv_sec =
2;<BR>delay.tv_nsec = 0;<BR>pthread_mutex_init(&mutex,
pthread_mutexattr_default);<BR>pthread_create( &reader,
pthread_attr_default, (void*)&reader_function,<BR>N U L L )
;<BR>writer_function( )<BR>void writer_function(void)<BR>{<BR>while( 1
)<BR>{<BR>pthread_mutex_lock( &mutex );<BR>if ( buffer_has_item == 0
)<BR>{<BR>buffer = make_new_item();<BR>buffer_has_item =
1;<BR>}<BR>pthread_mutex_unlock( &mutex );<BR>pthread_delay_np( &delay
);<BR>}<BR>}<BR>void reader_function(void)<BR>{<BR>while( 1
)<BR>{<BR>pthread_mutex_lock( &mutex );<BR>if ( buffer_has_item ==
1)<BR>{<BR>consume_item( buffer );<BR>buffer_has_item =
0;<BR>}<BR>pthread_mutex_unlock( &mutex );<BR>pthread_delay_np( &delay
);<BR>}<BR>}<BR>在上面的程序中,我们假定缓冲区只能保存一条信息,这样缓冲区只有两个状态,有一条信息或者没有信息。使用延迟是为了避免一个线程永远占有mutex。<BR>但mutex的缺点在于它只有两个状态,锁定和非锁定。POSIX的条件变量通过允许线程阻塞和等待另一个线程的信号方法,从而弥补了mutex的不足。当接受到一个信号时,阻塞线程将会被唤起,并试图获得相关的mutex的锁。
<P>
<P>
<P>
<CENTER><A
href="http://www.huihoo.com/joyfire.net/11.html#Content">[目录]</A></CENTER>
<HR>
<BR><A id=I262 name=I262></A>
<CENTER><B><FONT
size=+2>使用信号量协调程序</FONT></B></CENTER><BR>我们可以使用信号量重新看一下上面的读/写程序。涉及信号量的操作是semaphore_up、semaphore_down、semaphore_init、semaphore_destroy和semaphore_decrement。所有这些操作都只有一个参数,一个指向信号量目标的指针。<BR>void
reader_function(void);<BR>void writer_function(void);<BR>char buffer
;<BR>Semaphore writers_turn;<BR>Semaphore readers_turn;<BR>main(
)<BR>{<BR>pthread_t reader;<BR>semaphore_init( &readers_turn
);<BR>semaphore_init( &writers_turn );<BR>/* writer must go first
*/<BR>semaphore_down( &readers_turn );<BR>pthread_create( &reader,
pthread_attr_default,<BR>(void *)&reader_function, NULL);<BR>w r i t e r _ f
u n c t i o n ( ) ;<BR>}<BR>void writer_function(void)<BR>{<BR>w h i l e ( 1
)<BR>{<BR>semaphore_down( &writers_turn );<BR>b u ffer =
make_new_item();<BR>semaphore_up( &readers_turn );<BR>}<BR>}<BR>void
reader_function(void)<BR>{<BR>w h i l e ( 1 )<BR>{<BR>semaphore_down(
&readers_turn );<BR>consume_item( buffer );<BR>semaphore_up(
&writers_turn );<BR>}<BR>}<BR>这个例子也没有完全地利用一般信号量的所有函数。我们可以使用信号量重新编写“Hello
world” 的程序:<BR>void print_message_function( void *ptr );<BR>Semaphore
child_counter;<BR>Semaphore worlds_turn;<BR>main( )<BR>{<BR>pthread_t thread1,
thread2;<BR>char *message1 = "Hello";<BR>char *message2 = "Wo r l d "
;<BR>semaphore_init( &child_counter );<BR>semaphore_init( &worlds_turn
);<BR>semaphore_down( &worlds_turn ); /* world goes second
*/<BR>semaphore_decrement( &child_counter ); /* value now 0
*/<BR>semaphore_decrement( &child_counter ); /* value now -1 */<BR>/*<BR>*
child_counter now must be up-ed 2 times for a thread blocked on it<BR>* to be
released<BR>*<BR>* /<BR>pthread_create( &thread1,
pthread_attr_default,<BR>(void *) &print_message_function, (void *)
message1);<BR>semaphore_down( &worlds_turn
);<BR>pthread_create(&thread2, pthread_attr_default,<BR>(void *)
&print_message_function, (void *) message2);<BR>semaphore_down(
&child_counter );<BR>/* not really necessary to destroy since we are exiting
anyway */<BR>semaphore_destroy ( &child_counter );<BR>semaphore_destroy (
&worlds_turn );<BR>e x i t ( 0 ) ;<BR>}<BR>void print_message_function( void
*ptr )<BR>{<BR>char *message;<BR>message = (char *) ptr;<BR>printf("%s ",
message);<BR>fflush(stdout);<BR>semaphore_up( &worlds_turn
);<BR>semaphore_up( &child_counter );<BR>p t h r e a d _ e x i t ( 0 )
;<BR>}<BR>信号量c h i l d _ c o u n t e r用来强迫父线程阻塞,直到两个子线程执行完p r i n t
f语句和其后的semaphore_up( &child_counter )语句才继续执行。
<P>Semaphore.h
<P>#ifndef SEMAPHORES<BR>#define SEMAPHORES<BR>#include<BR>#include<BR>typedef
struct Semaphore<BR>{<BR>int v;<BR>pthread_mutex_t mutex;<BR>pthread_cond_t
cond;<BR>}<BR>S e m a p h o r e ;<BR>int semaphore_down (Semaphore * s);<BR>int
semaphore_decrement (Semaphore * s);<BR>int semaphore_up (Semaphore *
s);<BR>void semaphore_destroy (Semaphore * s);<BR>void semaphore_init (Semaphore
* s);<BR>int semaphore_value (Semaphore * s);<BR>int tw_pthread_cond_signal
(pthread_cond_t * c);<BR>int tw_pthread_cond_wait (pthread_cond_t * c,
pthread_mutex_t * m);<BR>int tw_pthread_mutex_unlock (pthread_mutex_t *
m);<BR>int tw_pthread_mutex_lock (pthread_mutex_t * m);<BR>void do_error (char
*msg);<BR># e n d i f
<P>Semaphore.c
<P>#include "semaphore.h"<BR>/ *<BR>* function must be called prior to semaphore
use.<BR>*<BR>* /<BR>v o i d<BR>semaphore_init (Semaphore * s)<BR>{<BR>s->v =
1;<BR>if (pthread_mutex_init (&(s->mutex), pthread_mutexattr_default) ==
-1)<BR>do_error ("Error setting up semaphore mutex");<BR>if (pthread_cond_init
(&(s->cond), pthread_condattr_default) == -1)<BR>do_error ("Error setting
up semaphore condition signal");<BR>* function should be called when there is no
longer a need for<BR>* the semaphore.<BR>*<BR>* /<BR>v o i
d<BR>semaphore_destroy (Semaphore * s)<BR>{<BR>if (pthread_mutex_destroy
(&(s->mutex)) == -1)<BR>do_error ("Error destroying semaphore
mutex");<BR>if (pthread_cond_destroy (&(s->cond)) == -1)<BR>do_error
("Error destroying semaphore condition signal");<BR>}<BR>/ *<BR>* function
increments the semaphore and signals any threads that<BR>* are blocked waiting a
change in the semaphore.<BR>*<BR>* /<BR>i n t<BR>semaphore_up (Semaphore *
s)<BR>{<BR>int value_after_op;<BR>tw_pthread_mutex_lock
(&(s->mutex));<BR>( s - > v ) + + ;<BR>value_after_op =
s->v;<BR>tw_pthread_mutex_unlock
(&(s->mutex));<BR>tw_pthread_cond_signal (&(s->cond));<BR>return
(value_after_op);<BR>}<BR>/ *<BR>* function decrements the semaphore and blocks
if the semaphore is<BR>* <= 0 until another thread signals a
change.<BR>*<BR>* /<BR>i n t<BR>semaphore_down (Semaphore * s)<BR>{<BR>int
value_after_op;<BR>tw_pthread_mutex_lock (&(s->mutex));<BR>while (s->v
<= 0)<BR>{<BR>tw_pthread_cond_wait (&(s->cond),
&(s->mutex));<BR>}<BR>( s - > v ) - - ;<BR>value_after_op =
s->v;<BR>tw_pthread_mutex_unlock (&(s->mutex));<BR>return
(value_after_op);<BR>}<BR>/ *<BR>* function does NOT block but simply decrements
the semaphore.<BR>* should not be used instead of down -- only for programs
where<BR>* multiple threads must up on a semaphore before another thread<BR>*
can go down, i.e., allows programmer to set the semaphore to<BR>* a negative
value prior to using it for synchronization.<BR>*<BR>* /<BR>i n
t<BR>semaphore_decrement (Semaphore * s)<BR>{<BR>int
value_after_op;<BR>tw_pthread_mutex_lock (&(s->mutex));<BR>s - > v - -
;<BR>value_after_op = s->v;<BR>tw_pthread_mutex_unlock
(&(s->mutex));<BR>return (value_after_op);<BR>}<BR>/ *<BR>* function
returns the value of the semaphore at the time the<BR>* critical section is
accessed. obviously the value is not guarenteed<BR>* after the function unlocks
the critical section. provided only<BR>* for casual debugging, a better approach
is for the programmar to<BR>* protect one semaphore with another and then check
its value.<BR>* an alternative is to simply record the value returned by
semaphore_up<BR>* or semaphore_down.<BR>*<BR>* /<BR>i n t<BR>semaphore_value
(Semaphore * s)<BR>{<BR>/* not for sync */<BR>int
value_after_op;<BR>tw_pthread_mutex_lock (&(s->mutex));<BR>value_after_op
= s->v;<BR>tw_pthread_mutex_unlock (&(s->mutex));<BR>return
(value_after_op);<BR>}<BR>/*
-------------------------------------------------------------------- */<BR>/*
The following functions replace standard library functions in that */<BR>/* they
exit on any error returned from the system calls. Saves us */<BR>/* from having
to check each and every call above. */<BR>/*
-------------------------------------------------------------------- */<BR>i n
t<BR>tw_pthread_mutex_unlock (pthread_mutex_t * m)<BR>{<BR>int
return_value;<BR>if ((return_value = pthread_mutex_unlock (m)) ==
-1)<BR>do_error ("pthread_mutex_unlock");<BR>return (return_value);<BR>}<BR>i n
t<BR>tw_pthread_mutex_lock (pthread_mutex_t * m)<BR>{<BR>int return_value;<BR>if
((return_value = pthread_mutex_lock (m)) == -1)<BR>do_error
("pthread_mutex_lock");<BR>return (return_value);<BR>}<BR>i n
t<BR>tw_pthread_cond_wait (pthread_cond_t * c, pthread_mutex_t * m)<BR>{<BR>int
return_value;<BR>if ((return_value = pthread_cond_wait (c, m)) ==
-1)<BR>do_error ("pthread_cond_wait");<BR>return (return_value);<BR>}<BR>i n
t<BR>tw_pthread_cond_signal (pthread_cond_t * c)<BR>{<BR>int return_value;<BR>if
((return_value = pthread_cond_signal (c)) == -1)<BR>do_error
("pthread_cond_signal");<BR>return (return_value);<BR>}<BR>/ *<BR>* function
just prints an error message and exits<BR>*<BR>* /<BR>v o i d<BR>do_error (char
*msg)<BR>{<BR>perror (msg);<BR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -