📄 11.html
字号:
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>
exit (1);<br>
}<p>
<p>
<p>
<center><A HREF="#Content">[目录]</A></center>
<hr><br><A NAME="I263" ID="I263"></A><center><b><font size=+2>代码例子</font></b></center><br>
<center><A HREF="#Content">[目录]</A></center>
<hr><br><A NAME="I264" ID="I264"></A><center><b><font size=+2>newthread</font></b></center><br>
/***********************************************************************<br>
Case study source code from the book `The Linux A to Z'<br>
by Phil Cornes. Published by Prentice Hall, 1996.<br>
Copyright (C) 1996 Phil Cornes<p>
This program is free software; you can redistribute it and/or modify<br>
it under the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -