标签:
互斥锁创建
有两种方法创建互斥锁,静态方式和动态方式。POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER 来静态初始化互斥锁,方法如下:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
在LinuxThreads实现中, pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。
动态方式是采用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