/**//* include globals */ #include "unpipc.h" #define MAXNITEMS 1000000 #define MAXNTHREADS 100 /**//* globals shared by threads */ int nitems; /**//* read-only by producer and consumer */ int buff[MAXNITEMS]; struct{ pthread_mutex_t mutex; int nput; /**//* next index to store */ int nval; /**//* next value to store */ } put ={ PTHREAD_MUTEX_INITIALIZER }; struct{ pthread_mutex_t mutex; pthread_cond_t cond; int nready; /**//* number ready for consumer */ } nready ={ PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER }; /**//* end globals */ void*produce(void*), *consume(void*); /**//* include main */ int main(int argc, char**argv) { int i, nthreads, count[MAXNTHREADS]; pthread_t tid_produce[MAXNTHREADS], tid_consume; if (argc !=3) err_quit("usage: prodcons6 <#items> <#threads>"); nitems = min(atoi(argv[1]), MAXNITEMS); nthreads = min(atoi(argv[2]), MAXNTHREADS); Set_concurrency(nthreads +1); /**//* 4create all producers and one consumer */ for (i =0; i < nthreads; i++) { count[i] =0; Pthread_create(&tid_produce[i], NULL, produce, &count[i]); } Pthread_create(&tid_consume, NULL, consume, NULL); /**//* wait for all producers and the consumer */ for (i =0; i < nthreads; i++) { Pthread_join(tid_produce[i], NULL); printf("count[%d] = %d/n", i, count[i]); } Pthread_join(tid_consume, NULL); exit(0); } /**//* end main */ /**//* include prodcons */ void* produce(void*arg) { for ( ; ; ) { Pthread_mutex_lock(&put.mutex); if (put.nput >= nitems) { Pthread_mutex_unlock(&put.mutex); return(NULL); /**//* array is full, we're done */ } buff[put.nput] = put.nval; put.nput++; put.nval++; Pthread_mutex_unlock(&put.mutex); Pthread_mutex_lock(&nready.mutex); if (nready.nready ==0) Pthread_cond_signal(&nready.cond);//发出信号 nready.nready++;//置为1 Pthread_mutex_unlock(&nready.mutex); *((int*) arg) +=1; } } void* consume(void*arg) { int i; for (i =0; i < nitems; i++) { Pthread_mutex_lock(&nready.mutex); while (nready.nready ==0) Pthread_cond_wait(&nready.cond, &nready.mutex);//wait条件变量 nready.nready--;//置为0 Pthread_mutex_unlock(&nready.mutex); if (buff[i] != i) printf("buff[%d] = %d/n", i, buff[i]); } return(NULL); } /**//* end prodcons */
typedef struct{ pthread_mutex_t rw_mutex; /**//* basic lock on this struct *///访问此读写锁使用的互斥锁 pthread_cond_t rw_condreaders; /**//* for reader threads waiting 读者线程使用*/ pthread_cond_t rw_condwriters; /**//* for writer threads waiting 写者线程使用*/ int rw_magic; /**//* for error checking 初始化成功后, 被设置为RW_MAGIC,所有函数测试此成员,检查调用者是否作为参数传递了指向某个已经初始化的读写锁的指针,读写锁摧毁时,被设置为0*/ int rw_nwaitreaders;/**//* the number waiting 读者计数器*/ int rw_nwaitwriters;/**//* the number waiting 写者计数器*/ int rw_refcount;//本读写锁的当前状态,-1表示是写入锁(任意时刻只有一个),0表示可用,大于0表示当前容纳着的读出锁数目 /**//* 4-1 if writer has the lock, else # readers holding the lock */ } pthread_rwlock_t;
int pthread_rwlock_init(pthread_rwlock_t *rw, pthread_rwlockattr_t *attr) { int result; if (attr != NULL) return(EINVAL); /**//* not supported */ 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_destroy(&rw->rw_condreaders); err2: pthread_mutex_destroy(&rw->rw_mutex); err1: return(result); /**//* an errno value */ }
int pthread_rwlock_destroy(pthread_rwlock_t *rw) { //检查参数是否有效 if (rw->rw_magic != RW_MAGIC) return(EINVAL); if (rw->rw_refcount !=0|| rw->rw_nwaitreaders !=0|| rw->rw_nwaitwriters !=0) return(EBUSY); pthread_mutex_destroy(&rw->rw_mutex); pthread_cond_destroy(&rw->rw_condreaders); pthread_cond_destroy(&rw->rw_condwriters); rw->rw_magic =0; return(0); }
int pthread_rwlock_rdlock(pthread_rwlock_t *rw) { int result; //检查参数是否有效 if (rw->rw_magic != RW_MAGIC) return(EINVAL); //操作读写锁前,先给其互斥锁上锁 if ( (result = pthread_mutex_lock(&rw->rw_mutex)) !=0) return(result); /**//* 4give preference to waiting writers */ while (rw->rw_refcount <0|| rw->rw_nwaitwriters >0) {// rw_refcount 小于0(表示有写者持有读写锁),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++; /**//* another reader has a read lock */ pthread_mutex_unlock(&rw->rw_mutex); return (result); }
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rw) { int result; if (rw->rw_magic != RW_MAGIC) return(EINVAL); if ( (result = pthread_mutex_lock(&rw->rw_mutex)) !=0) return(result); if (rw->rw_refcount <0|| rw->rw_nwaitwriters >0) result = EBUSY; /**//* held by a writer or waiting writers */ else rw->rw_refcount++; /**//* increment count of reader locks */ pthread_mutex_unlock(&rw->rw_mutex); return(result); }
int pthread_rwlock_wrlock(pthread_rwlock_t *rw) { int result; if (rw->rw_magic != RW_MAGIC) return(EINVAL); 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 pthread_rwlock_trywrlock(pthread_rwlock_t *rw) { int result; if (rw->rw_magic != RW_MAGIC) return(EINVAL); if ( (result = pthread_mutex_lock(&rw->rw_mutex)) !=0) return(result); if (rw->rw_refcount !=0) result = EBUSY; /**//* held by either writer or reader(s) */ else rw->rw_refcount =-1; /**//* available, indicate a writer has it */ pthread_mutex_unlock(&rw->rw_mutex); return(result); }
int pthread_rwlock_unlock(pthread_rwlock_t *rw) { int result; if (rw->rw_magic != RW_MAGIC) return(EINVAL); if ( (result = pthread_mutex_lock(&rw->rw_mutex)) !=0) return(result); if (rw->rw_refcount >0) rw->rw_refcount--; /**//* releasing a reader */ elseif (rw->rw_refcount ==-1) rw->rw_refcount =0; /**//* releasing a reader */ else err_dump("rw_refcount = %d", rw->rw_refcount); /**//* 4give preference to waiting writers over waiting readers */ if (rw->rw_nwaitwriters >0) { if (rw->rw_refcount ==0) result = pthread_cond_signal(&rw->rw_condwriters); }elseif (rw->rw_nwaitreaders >0) result = pthread_cond_broadcast(&rw->rw_condreaders); pthread_mutex_unlock(&rw->rw_mutex); return(result); }
int pthread_rwlock_unlock(pthread_rwlock_t *rw) { int result; if (rw->rw_magic != RW_MAGIC) return(EINVAL); if ( (result = pthread_mutex_lock(&rw->rw_mutex)) !=0) return(result); if (rw->rw_refcount >0) rw->rw_refcount--; /**//* releasing a reader */ elseif (rw->rw_refcount ==-1) rw->rw_refcount =0; /**//* releasing a writer */ else err_dump("rw_refcount = %d", rw->rw_refcount); /**//* 4give preference to waiting writers over waiting readers */ //写者优先,而只有一个写者 if (rw->rw_nwaitwriters >0) { if (rw->rw_refcount ==0) result = pthread_cond_signal(&rw->rw_condwriters);//通知等待的那个写者 }elseif (rw->rw_nwaitreaders >0) result = pthread_cond_broadcast(&rw->rw_condreaders);//通知所有等待的读者 pthread_mutex_unlock(&rw->rw_mutex); return(result); }