APUE中文第三版11章读写锁的一个可运行的例子

我的测试环境是CentOS7(内核版本3.10.0),X86_64.

头文件: wrlock.h

#ifndef _WRLOCK_H
#define _WRLOCK_H

#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>

struct job {
    struct job  *j_next;
    struct job  *j_prev;
    pthread_t   tid;
    void *( *job_func)( void *);
};

struct queue {
    struct job      *q_head;
    struct job      *q_tail;
    pthread_rwlock_t    q_lock; 
};

int queue_init( struct queue *qp );
void job_insert( struct queue *qp, struct job *jp );
void job_append( struct queue *qp, struct job *jp );
void job_remove( struct queue *qp, struct job *jp );
struct job *job_find( struct queue *qp, pthread_t tid );

#endif

队列的相关操作,这一部分与书上的基本一样。
11_14.c

#include "wrlock.h"

int
queue_init( struct queue *qp )
{
    int err;

    qp->q_head = qp->q_tail = NULL;
    if ((err = pthread_rwlock_init(&qp->q_lock,NULL)) != 0)
        return err;
    return 0;
}

/* insert a job at the head of queue */
void 
job_insert( struct queue *qp, struct job *jp )
{
    pthread_rwlock_wrlock(&qp->q_lock);
    jp->j_next = qp->q_head;
    jp->j_prev = NULL;
    if ( qp->q_head != NULL )
        qp->q_head->j_prev = jp;
    else    
        qp->q_tail = jp;
    qp->q_head = jp;
    pthread_rwlock_unlock(&qp->q_lock);
}


/* append a job on the tail of queue */
void 
job_append( struct queue *qp, struct job *jp )
{
    pthread_rwlock_wrlock(&qp->q_lock);
    jp->j_next = NULL;
    jp->j_prev = qp->q_tail;
    if ( qp->q_tail != NULL )
        qp->q_tail->j_next = jp;
    else    
        qp->q_head = jp;
    qp->q_tail = jp;
    pthread_rwlock_unlock(&qp->q_lock);
}

void
job_remove( struct queue *qp, struct job *jp )
{
    pthread_rwlock_wrlock(&qp->q_lock);
    /* 
    ** remove the head job,maybe jp pointing the only job.
    */
    if (jp == qp->q_head){
        qp->q_head = jp->j_next;
        if (jp->j_next != NULL)
            jp->j_next->j_prev = NULL;
        else 
            qp->q_tail = NULL;
    }  /* 
       ** remove the tail job, if jp pointing the only job, 
       ** then if{} statements has executed, we can't get here.
       */
    else if ( jp == qp->q_tail ){
        qp->q_tail = jp->j_prev;
        jp->j_prev->j_next = NULL;

    } else{
        jp->j_next->j_prev = jp->j_prev;
        jp->j_prev->j_next = jp->j_next;
    }
    pthread_rwlock_unlock(&qp->q_lock);
}

struct job *
job_find( struct queue *qp, pthread_t tid )
{
    struct job *jtmp;

    if(pthread_rwlock_rdlock(&qp->q_lock) != 0)
        return NULL;

    for ( jtmp = qp->q_head; jtmp != NULL; jtmp = jtmp->j_next ){
        if (pthread_equal(jtmp->tid,tid) != 0)
            break;
    }
    pthread_rwlock_unlock(&qp->q_lock);
    return jtmp;
}

main函数部分,主线程负责初始化队列,将产生的job插入队列,job结构中有指派的线程的id,以及给出的任务(函数指针)。其他的工作线程从队列中找到属于自己的job,然后利用这个函数指针调用函数,完成任务。任务很简单,就是打印一句话。

main.c:

#include "wrlock.h"
#define _GNU_SOURCE

void *
task1( void *str1 )
{
    printf("I am thread 1, %s\n",(char *)str1);
}

void *
task2( void *str2 )
{
    printf("I am thread 2, %s\n",(char *)str2);
}

void *
task3( void *str3 )
{
    printf("I am thread 3, %s\n",(char *)str3);
}

void *
thr1_func( void *arg ) //arg points to queue.
{
    pthread_t   tid;
    struct job  *jp1;

    tid = pthread_self();
    while (1){
        if ((jp1 = job_find(arg,tid)) != NULL){
            jp1->job_func("task completly!");
            job_remove(arg,jp1); 
            free(jp1);
        }else{
            pthread_yield();
        }
    }
}

void *
thr2_func( void *arg ) //arg points to queue.
{
    pthread_t   tid;
    struct job  *jp2;

    tid = pthread_self();
    while (1){
        if ((jp2 = job_find(arg,tid)) != NULL){
            jp2->job_func("task completly!");
            job_remove(arg,jp2); 
            free(jp2);
        }else{
            pthread_yield();
        }
    }
}

void *
thr3_func( void *arg ) //arg points to queue.
{
    pthread_t   tid;
    struct job  *jp3;

    tid = pthread_self();
    while (1){
        if ((jp3 = job_find(arg,tid)) != NULL){
            jp3->job_func("task completly!");
            job_remove(arg,jp3); 
            free(jp3);
        }else{
            pthread_yield();
        }
    }
}

int 
main( void )
{
    unsigned long   n;
    int         err;
    int         foo;
    struct job  *jobptr;
    struct queue    *qptr;
    pthread_t   tid[3];
    void *(*func[3])(void *) = { task1, task2, task3 };

    /* initialise the queue */
    if ((qptr = malloc(sizeof( struct queue ))) == NULL)
        exit(-1);
    queue_init(qptr);

    /* produce task in main thread */
    err = pthread_create(&tid[0],NULL,thr1_func,qptr);
    if (err != 0)
        exit(-1);
    else
        printf("create thread 1 success\n");

    err = pthread_create(&tid[1],NULL,thr2_func,qptr);
    if (err != 0)
        exit(-1);
    else
        printf("create thread 2 success\n");

    err = pthread_create(&tid[2],NULL,thr3_func,qptr);
    if (err != 0)
        exit(-1);
    else
        printf("create thread 3 success\n");

    for ( n = 1; n <= 10; n++){
        if ((jobptr = malloc(sizeof(struct job))) == NULL)
            exit(-1);
        foo = rand()%3;
        jobptr->tid = tid[foo];
        jobptr->job_func = func[foo];
        job_insert(qptr,jobptr);
    }

    sleep(10);
    exit(0);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值