本次使用linux信号量来实现线程读写同步,还是实现之前写的那个读和写数组的例子,本次在写的过程中出现一个死锁问题,原因是先进入临界区,然后等待信号量,这样造成读函数在等待信号量,写函数在等待进入临界区,所以修改了下程序,先进入信号量的等待,再进入临界区的等待,这也说明了我们写程序时不能长时间占用临界区,会很容易造成死锁。程序代码如下:
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#define MAX_NUM 100
#define MAX_THREAD 10
static int g_array[MAX_NUM];
volatile int g_num_gen = 0;
volatile int g_count = 0;
static int g_stop = 0;
static sem_t g_sem_full;
static sem_t g_sem_empty;
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
void *write_thread(void *arg)
{
int i;
while(!g_stop ){
sem_wait(&g_sem_empty);
pthread_mutex_lock(&g_mutex);
if( g_stop ){
break;
}
g_array[g_count++] = g_num_gen++;
printf("write %d count=%d tid=%lu\n", g_array[g_count-1], g_count, pthread_self() );
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_full);
usleep(1000*500);
}
for(i=0; i<MAX_THREAD; i++){
sem_post(&g_sem_full);
}
pthread_mutex_unlock(&g_mutex);
return NULL;
}
void *read_thread(void *arg)
{
int i;
while(!g_stop ){
sem_wait(&g_sem_full);
pthread_mutex_lock(&g_mutex);
if( g_stop ){
break;
}
printf("read %d count=%d tid=%lu\n", g_array[g_count-1], g_count, pthread_self() );
g_count--;
pthread_mutex_unlock(&g_mutex);
sem_post(&g_sem_empty);
usleep(1000*500);
}
for(i=0; i<MAX_THREAD; i++){
sem_post(&g_sem_empty);
}
pthread_mutex_unlock(&g_mutex);
return NULL;
}
int main()
{
int i;
pthread_t *tid;
void *thread_result;
if (sem_init(&g_sem_full, 1, 0) == -1){
fprintf( stderr, "Failed to initialize semaphore g_sem_full\n");
return -1;
}
if( sem_init(&g_sem_empty, 1, MAX_NUM) == -1 ){
fprintf( stderr, "Failed to initialize semaphore g_sem_empty\n");
return -1;
}
if ((tid = (pthread_t *)calloc(MAX_THREAD, sizeof(pthread_t))) == NULL) {
perror("Failed to allocate space for thread IDs");
return -1;
}
/* 开启写线程 */
for(i=0; i<8; i++){
pthread_create(tid+i, NULL, write_thread, 0 );
}
/* 开启读线程 */
for(i=8; i<MAX_THREAD; i++) {
pthread_create(tid+i, NULL, read_thread, 0 );
}
/* 由用户输入任意值,然后各个线程安全退出 */
getchar();
g_stop = 1;
for(i=0; i<MAX_THREAD; i++ ){
pthread_join(tid[i], &thread_result);
}
free(tid);
sem_destroy(&g_sem_empty);
sem_destroy(&g_sem_full);
return 0;
}