码迷,mamicode.com
首页 > 编程语言 > 详细

多线程互斥-读写者问题

时间:2015-07-08 20:25:25      阅读:230      评论:0      收藏:0      [点我收藏+]

标签:

互斥量(mutex)

互斥锁创建

有两种方法创建互斥锁,静态方式和动态方式。POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER 来静态初始化互斥锁,方法如下:

  1. pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;在LinuxThreads实现中, pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。

  2. 动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下:

     int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t
             *mutexattr)

    其中mutexattr用于指定互斥锁属性(见下),如果为NULL则使用缺省属性。 pthread_mutex_destroy ()用于注销一个互斥锁,API定义如下:

     int pthread_mutex_destroy(pthread_mutex_t *mutex)

锁操作

锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到, 而必须等待解锁。对于普通锁和适应锁类型,解锁者可以是同进程内任何线程; 而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由 加锁者解锁,但实验结果表明并没有这种限制,这个不同目前还没有得到解释。在同一进程中 的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。

int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)

pthread_mutex_trylock() 语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回 EBUSY而不是挂起等待。

 

读写者问题:

读者————写者问题是一个用信号量实现的经典进程同步问题。在系统中,一个数据集(如文件或 记录) 被几个并发进程共享,这些线程分两类,一部分只要求进行读操作,称之为“读者”; 另一类要求写或修改操作,我们称之为“写者“。一般而言,对一个数据集,为了保证数据的完整 性、正确性,允许多个读者进程同时访问,但是不允许一个写者进程同其它任何一个进程(读者 或者写者)同时访问,而这类问题就称之为"读者-写者"问题。

/*********    说明:
*********    1.要让读者与写者之间、以及写者与写者之问要互斥地访同数据集;
*********    2.在无写进程到来时各读者可同时访问数据集;
*********    3.在读者和写者都等待时访问时写者优先.
*********/

#include <pthread.h>
#include <signal.h>
#include <stdio.h>
//#include "apue.h"

#define R 5 // reader NO.
#define W 5 // reader and writer NO.

pthread_mutex_t rd = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t wr = PTHREAD_MUTEX_INITIALIZER;

int readCount = 0; //临界资源

void* reader(void *arg)
{
    int n = W;
    int id = *(int *)arg;
    while (n --)
    {
         sleep(rand()%3);
         pthread_mutex_lock(&rd);
         readCount++; //对于临街资源必须做到互斥访问,同一时间只有一个线程在操作.
         if( readCount ==1 ) //当只要有读线程时就会锁住,并不用>1时都锁住,只要锁一次,其他>1的情况均没有释放,在等于0的时候释放就行
         {
             pthread_mutex_lock(&wr);
         }
         pthread_mutex_unlock(&rd);
         printf("reader %d is reading, current read count[%d]\n", id, readCount); //这段代码表示多个读者之间是可以并行执行的.
         sleep(rand()%3);
         pthread_mutex_lock(&rd);
         readCount--;

         if(readCount == 0)
         {
              pthread_mutex_unlock(&wr);
         }
         pthread_mutex_unlock(&rd);
         printf("reader %d is leaving, current read count[%d]\n", id, readCount);
    }
    printf("-----reader %d has done ----, current read count[%d]\n", id, readCount);
}

void *writer(void *arg)
{
     int n = W;
     while(n--)
     {
         sleep(rand()%3);
         pthread_mutex_lock(&wr); //写线程之间也是互斥的.
         printf("\twriter is writing\n");
         sleep(rand()%3);
         pthread_mutex_unlock(&wr);
         printf("\twriter is leaving\n");
     }
     printf("-----writer has done -----\n");
}

int main(int argc, const char *argv[])
{
     int err;
     pthread_t tid[R], writerTid;
     int i;

     err = pthread_create(&writerTid, NULL, writer, (void *)NULL);
     if (err != 0)
     {
          printf("can‘t create process for writer");
     }

     for(i = 0; i < R; i++)
     {
         err = pthread_create(&tid[i], NULL, reader, &i);
         if (err != 0)
         {
             printf("can‘t create process for reader");
         }
     }

     //pause();
     pthread_join(tid[0],&err);
     printf("thread 1 exit code %d\n", (int)err);

     pthread_join(tid[1],&err);
     printf("thread 2 exit code %d\n",(int)err);

     pthread_join(tid[2],&err);
     printf("thread 3 exit code %d\n", (int)err);

     pthread_join(tid[3],&err);
     printf("thread 4 exit code %d\n", (int)err);

     pthread_join(tid[4],&err);
     printf("thread 5 exit code %d\n", (int)err);
     //while(1);
     pthread_join(writerTid,&err);
     printf("write thread  exit code %d\n", (int)err);
     return 0;
}

运行结果是:

reader 2 is reading, current read count[1]
reader 1 is reading, current read count[2]
reader 1 is leaving, current read count[2]
reader 1 is reading, current read count[3]
reader 3 is reading, current read count[3]
reader 5 is reading, current read count[4]
reader 2 is leaving, current read count[3]
reader 4 is reading, current read count[4]
reader 1 is leaving, current read count[3]
reader 5 is leaving, current read count[2]
reader 3 is leaving, current read count[1]
reader 3 is reading, current read count[2]
reader 3 is leaving, current read count[1]
reader 4 is leaving, current read count[0]
    writer is writing
    writer is leaving
reader 5 is reading, current read count[1]
reader 5 is leaving, current read count[2]
reader 4 is reading, current read count[3]
reader 3 is reading, current read count[5]
reader 1 is reading, current read count[5]
reader 5 is reading, current read count[4]
reader 2 is reading, current read count[2]
reader 5 is leaving, current read count[4]
reader 2 is leaving, current read count[3]
reader 4 is leaving, current read count[2]
reader 4 is reading, current read count[3]
reader 4 is leaving, current read count[2]
reader 4 is reading, current read count[3]
reader 3 is leaving, current read count[2]
reader 3 is reading, current read count[3]
reader 1 is leaving, current read count[2]
reader 5 is reading, current read count[3]
reader 2 is reading, current read count[4]
reader 3 is leaving, current read count[3]
reader 5 is leaving, current read count[3]
reader 1 is reading, current read count[4]
reader 1 is leaving, current read count[4]
reader 3 is reading, current read count[4]
reader 5 is reading, current read count[5]
reader 4 is leaving, current read count[3]
reader 2 is leaving, current read count[2]
reader 5 is leaving, current read count[1]
-----reader 5 has done ----, current read count[1]
reader 3 is leaving, current read count[0]
-----reader 3 has done ----, current read count[1]
reader 1 is reading, current read count[1]
reader 4 is reading, current read count[2]
reader 4 is leaving, current read count[1]
-----reader 4 has done ----, current read count[1]
reader 2 is reading, current read count[2]
reader 1 is leaving, current read count[1]
-----reader 1 has done ----, current read count[1]
thread 1 exit code 51
reader 2 is leaving, current read count[0]
    writer is writing
    writer is leaving
reader 2 is reading, current read count[1]
reader 2 is leaving, current read count[0]
-----reader 2 has done ----, current read count[0]
    writer is writing
    writer is leaving
thread 2 exit code 51
thread 3 exit code 51
thread 4 exit code 51
thread 5 exit code 51
    writer is writing
    writer is leaving
    writer is writing
    writer is leaving
-----writer has done -----
write thread  exit code 27

从log可以看出这是个读者优先的算法这是一种最简单的解决办法: 当没有写进程正在访问共享数据集时,读进程可以进入访问,否则必须等待。当读者访问完毕,写者才有机会获得临界区的访问权,所以说是读者优先.而读者优先的算法存在"饿死 写者"线程的问题:只要有读者不断到来,写者就要持久地等待,直到所有的读者都读完且没有新的读者到来时写者才能写数据集。而在很多情况下我们需要避免"饿死写者",故而采用写者优先算法:

在写者优先算法中,我们要实现的目标是:

1.要让读者与写者之间、以及写者与写者之问要互斥地访同数据集;

2.在无写进程到来时各读者可同时访问数据集;

3.在读者和写者都等待时访问时写者优先.

在实现写者优先时,增加一个互斥量,用于写者优先。当有写者来时,就不在允许读者去读取数据, 等待正在读数据的读者完成以后开始写数据,以此实现写者优先。

写者优先的代码如下

多线程互斥-读写者问题

标签:

原文地址:http://www.cnblogs.com/biglucky/p/4630947.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!