2009-05-24

Linux 下的线程读写锁

有一种写优先读写锁,有如下特点: 1)多个读者可以同时进行读 2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行) 3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者) 在Solaris 中直接提供了读写锁, 但是在Linux 中只提供了线程的读写锁, 这里记录了一些读写锁的资料. 1.Solaris .vs. Linux Posix 库函数
Solaris 库(lib 线程)Linux POSIX 库(libp 线程)操作
sema_destroy()sem_destroy()销毁信号状态。
sema_init()sem_init()初始化信号。
sema_post()sem_post()增加信号。
sema_wait()sem_wait()阻止信号计数。
sema_trywait()sem_trywait()减少信号计数。
mutex_destroy()pthread_mutex_destroy()销毁或禁用与互斥对象相关的状态。
mutex_init()pthread_mutex_init()初始化互斥变量。
mutex_lock()pthread_mutex_lock()锁定互斥对象和块,直到互斥对象被释放。
mutex_unlock()pthread_mutex_unlock()释放互斥对象。
cond_broadcast()pthread_cond_broadcast()解除对等待条件变量的所有线程的阻塞。
cond_destroy()pthread_cond_destroy()销毁与条件变量相关的任何状态。
cond_init()pthread_cond_init()初始化条件变量。
cond_signal()pthread_cond_signal()解除等待条件变量的下一个线程的阻塞。
cond_wait()pthread_cond_wait()阻止条件变量,并在最后释放它。
rwlock_init()pthread_rwlock_init()初始化读/写锁。
rwlock_destroy()pthread_rwlock_destroy()锁定读/写锁。
rw_rdlock()pthread_rwlock_rdlock()读取读/写锁上的锁。
rw_wrlock()pthread_rwlock_wrlock()写读/写锁上的锁。
rw_unlock()pthread_rwlock_unlock()解除读/写锁。
rw_tryrdlock()pthread_rwlock_tryrdlock()读取非阻塞读/写锁上的锁。
rw_trywrlock()pthread_rwlock_trywrlock()写非阻塞读/写锁上的锁。
2.使用mutex 来实现 设置三个互斥信号量: rwmutex 用于写者与其他读者/写者互斥的访问共享数据 rmutex 用于读者互斥的访问读者计数器readcount nrmutex 用于写者等待已进入读者退出,所有读者退出前互斥写操作 var rwmutex,rmutex,nrmutex:semaphore:=1,1,1; int readcount=0; cobegin reader begin P(rwmutex); P(rmutex); readcount++; if (readcount == 1) P(nrmutex); //有读者进入,互斥写操作 V(rmutex); V(rwmutex); //及时释放读写互斥信号量,允许其它读、写进程申请资源读数据; P(rmutex); readcount--; if(readcount == 0) V(nrmutex); //所有读者退出,允许写更新 V(rmutex); End writer begin P(rwmutex); //互斥后续其它读者、写者 P(nrmutex); //如有读者正在读,等待所有读者读完 写更新; V(nrmutex); //允许后续新的第一个读者进入后互斥写操作 V(rwmutex); //允许后续新读者及其它写者 End coend 3. 利用pthread_cond_* & pthread_mutex_* 实现rw_lock #include <pthread.h> #include <cstdlib> #include <ctime> #include <iostream> using namespace std; class RWLock { private : pthread_mutex_t cnt_mutex; pthread_cond_t rw_cond; int rd_cnt, wr_cnt; RWLock(const RWLock&); RWLock& operator= (const RWLock&); public : RWLock(): rd_cnt(0),wr_cnt(0) { pthread_mutex_init(&cnt_mutex, NULL); pthread_cond_init(&rw_cond, NULL); } void get_shared_lock() { pthread_mutex_lock(&cnt_mutex); while (wr_cnt >0) { pthread_cond_wait(&rw_cond,&cnt_mutex); } rd_cnt++; pthread_mutex_unlock(&cnt_mutex); } void release_shared_lock() { pthread_mutex_lock(&cnt_mutex); rd_cnt--; if (0 == rd_cnt) { pthread_cond_signal(&rw_cond); } pthread_mutex_unlock(&cnt_mutex); } void get_exclusive_lock() { pthread_mutex_lock(&cnt_mutex); while (rd_cnt+wr_cnt>0) { pthread_cond_wait(&rw_cond,&cnt_mutex); } wr_cnt++; pthread_mutex_unlock(&cnt_mutex); } void release_exclusive_lock() { pthread_mutex_lock(&cnt_mutex); wr_cnt--; pthread_cond_broadcast(&rw_cond); pthread_mutex_unlock(&cnt_mutex); } ~RWLock() { pthread_mutex_destroy(&cnt_mutex); pthread_cond_destroy(&rw_cond); } }; class Test { private : RWLock lock; static void* shared_task_handler(void* arg) { Test* testptr = static_cast<Test*>(arg); testptr->lock.get_shared_lock(); //do the shared task here testptr->lock.release_shared_lock(); } static void * exclusive_task_handler(void * arg) { Test* testptr = static_cast<Test*>(arg); testptr->lock.get_exclusive_lock(); //do the exclusive task here testptr->lock.release_exclusive_lock(); } public : typedef void* (*ThreadFunc) (void*); void start() { srand(time(NULL)); const int THREADS_NO=rand()%100; pthread_t* threads = new pthread_t[THREADS_NO]; for(int i=0; i<THREADS_NO; i++) { ThreadFunc tmpfunc = rand()%2? shared_task_handler : exclusive_task_handler; if (pthread_create(threads+i,NULL,tmpfunc,this)) { cerr << "pthread_create fails" << endl; exit(1); } } for(int i=0; i<THREADS_NO; i++) { pthread_join(threads[i],NULL); } delete[] threads; } }; int main() { Test tmptest; tmptest.start(); }

没有评论: