壁虎不会漫步壁虎不会漫步04-19 07:19

Linux使用互斥锁和条件变量实现读写锁(写优先)

(1)只要没有线程持有某个给定的读写锁用于写,那么任意数目的线程可以持有该读写锁用于读

(2)仅当没有线程持有某个读写锁用于读或用于写时,才能分配该读写锁用于写

换一种说法就是,只要没有线程在修改(写)某个给定的数据,那么任意数目的线程都可以拥有该数据的访问权(读)。仅当没有其它线程在读或者修改(写)某个给定的数据时,当前线程才可以修改(写)它。

因此,读为共享,写为独占。

本程序只实现了一种可能,即优先考虑等待着的写入者,可有其他实现方案。

//my_pthread_rwlock.h

#pragma once

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

typedef struct
{
    pthread_mutex_t rw_mutex;
    pthread_cond_t  rw_condreaders;
    pthread_cond_t  rw_condwriters;
    int             rw_magic;
    int             rw_nwaitreaders;
    int             rw_nwaitwriters;
    int             rw_refcount;       // 0 >0 ==-1
}my_pthread_rwlock_t;

#define  RW_MAGIC  0x20180326
#define  EBUSY 22
#define MY_PTHREAD_RWLOCK_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER,RW_MAGIC,0,0,0}

typedef int  my_pthread_rwlockattr_t;


int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr);
int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *rw);
int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *rw);

//my_pthread_rwlock.c

#include"my_pthread_rwlock.h"
#include<pthread.h>
int my_pthread_rwlock_init(my_pthread_rwlock_t *rw, my_pthread_rwlockattr_t *attr)
{
	int result;
	if(attr != NULL)
		return -1;
	if((result = pthread_mutex_init(&rw->rw_mutex,NULL))!=0)
		goto err1;
	if((result = pthread_cond_init(&rw->rw_condreaders,NULL))!=0)
		goto err2;
	if((result = pthread_cond_init(&rw->rw_condwriters,NULL))!=0)
		goto err3;
	rw->rw_nwaitreaders=0;
	rw->rw_nwaitwriters=0;
	rw->rw_refcount=0;
	rw->rw_magic=RW_MAGIC;
	return 0;
err3:pthread_cond_destory(&rw->rw_condreaders);
err2:pthread_mutex_destory(&rw->rw_mutex);
err1:return result;

}
int my_pthread_rwlock_rdlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    while(rw->rw_refcount<0 || rw->rw_nwaitwriters>0)
    {
        rw->rw_nwaitreaders++;
        result = pthread_cond_wait(&rw->rw_condreaders, &rw->rw_mutex);
        rw->rw_nwaitreaders--;
        if(result != 0)
            break;
    }
    if(result == 0)
        rw->rw_refcount++;
    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}

int my_pthread_rwlock_wrlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;

    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    while(rw->rw_refcount != 0)
    {
        rw->rw_nwaitwriters++;
        result = pthread_cond_wait(&rw->rw_condwriters, &rw->rw_mutex);
        rw->rw_nwaitwriters--;
        if(result != 0)
            break;
    }
    if(result == 0)
        rw->rw_refcount = -1;

    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}

int my_pthread_rwlock_unlock(my_pthread_rwlock_t *rw)
{
    int result;
    if(rw->rw_magic != RW_MAGIC)
        return -1;
    if((result = pthread_mutex_lock(&rw->rw_mutex)) != 0)
        return result;

    if(rw->rw_refcount > 0)
        rw->rw_refcount--;
    else if(rw->rw_refcount == -1)
        rw->rw_refcount = 0;
    else
        printf("unlock error.\n");

    if(rw->rw_nwaitwriters > 0)
    {
        if(rw->rw_refcount == 0)
        {
            result = pthread_cond_signal(&rw->rw_condwriters);
        }
    }
    else if(rw->rw_nwaitreaders > 0)
        result = pthread_cond_broadcast(&rw->rw_condreaders);

    pthread_mutex_unlock(&rw->rw_mutex);
    return result;
}
int my_pthread_rwlock_tryrdlock(my_pthread_rwlock_t *rw)
{
	int result;
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if((result = pthread_mutex_lock(&rw->rw_mutex))!=0)
		return result;
	if(rw->rw_refcount!=0||rw->rw_nwaitwriters>0)
		result=EBUSY;
	else
		rw->rw_refcount++;
	return result;
}
int my_pthread_rwlock_trywrlock(my_pthread_rwlock_t *rw)
{
	int result;
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if((result = pthread_mutex_lock(&rw->rw_mutex))!=0)
		return result;
	if(rw->rw_refcount!=0)
		result=EBUSY;
	else
		rw->rw_refcount=-1;
	pthread_mutex_unlock(&rw->rw_mutex);
	return result;
}
int my_pthread_rwlock_destroy(my_pthread_rwlock_t *rw)
{
	if(rw->rw_magic!=RW_MAGIC)
		return -1;
	if(rw->rw_refcount!=0||rw->rw_nwaitreaders!=0||rw->rw_nwaitwriters!=0)
		return EBUSY;
	pthraed_mutex_destory(&rw->rw_mutex);
	pthread_cond_destory(&rw->rw_condreaders);
	pthread_cond_destory(&rw->rw_condwriters);
	rw->rw_magic=0;
	return 0;

}

//main.c

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include"my_pthread_rwlock.h"

my_pthread_rwlock_t rwlock = MY_PTHREAD_RWLOCK_INITIALIZER;

void * thread_fun1(void *arg)
{
}
void * thread_fun2(void *arg)
{
}
void * thread_fun3(void *arg)
{ 
}

int main()
{
    pthread_t tid1, tid2, tid3;
    pthread_create(&tid1, NULL, thread_fun1, NULL);
    sleep(1);
    pthread_create(&tid2, NULL, thread_fun2, NULL);
    pthread_create(&tid3, NULL, thread_fun3, NULL);

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);
    return 0;
}
            

官场书屋二维码

000
评论