/* g++ -Wall -o rwlock rwlock.cpp -lpthread * * 一个写优先读写锁的实现,多线程频繁读,多线程少量写,同时写优先,性能极佳。 * 当写锁(独占锁)lock成功的必要条件是: * 1. 将写锁计数++; * 2. 会阻塞后续对读锁(共享锁)的读; * 3. 等待读锁的计数为0; * 4. 等待写锁的计数为1; * */ #include <pthread.h> #include <cstdlib> #include <ctime> #include <iostream> #include <time.h> 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_t tag = pthread_self(); pthread_mutex_lock(&cnt_mutex); rd_cnt++; time_t now = time(NULL); printf("[%lu]r_lock[thread_0x%x] r=%d w=%d\n", now, (int)tag, rd_cnt, wr_cnt); while (wr_cnt >0) { printf("\t\t r_lock wait for wr_cnt[%d]\n", wr_cnt); pthread_cond_wait(&rw_cond,&cnt_mutex); } pthread_mutex_unlock(&cnt_mutex); } void release_shared_lock() { pthread_t tag = pthread_self(); pthread_mutex_lock(&cnt_mutex); rd_cnt--; time_t now = time(NULL); printf("[%lu]r_unlock[thread_0x%x] r=%d w=%d\n", now, (int)tag, rd_cnt, wr_cnt); if (0 == rd_cnt) { printf("\t\t r_unlock[thread_0x%x] rd_cnt=0, so singal to wr_cnt[%d]\n", (int)tag, wr_cnt); pthread_cond_signal(&rw_cond); } pthread_mutex_unlock(&cnt_mutex); } void get_exclusive_lock() { pthread_t tag = pthread_self(); pthread_mutex_lock(&cnt_mutex); wr_cnt++; time_t now = time(NULL); printf("=====[%lu]w_lock[thread_0x%x] r=%d w=%d\n", now, (int)tag, rd_cnt, wr_cnt); while (rd_cnt+wr_cnt>=2) { printf("\t\t w_lock wait r=%d w=%d\n", rd_cnt, wr_cnt); pthread_cond_wait(&rw_cond,&cnt_mutex); } printf("=====\t\t w_lock[thread_0x%x] get ok r=%d w=%d\n", (int)tag, rd_cnt, wr_cnt); pthread_mutex_unlock(&cnt_mutex); } void release_exclusive_lock() { pthread_t tag = pthread_self(); pthread_mutex_lock(&cnt_mutex); wr_cnt--; time_t now = time(NULL); printf("=====[%lu]w_unlock[thread_0x%x] r=%d w=%d, then broadcast\n", now, (int)tag, rd_cnt, wr_cnt); pthread_cond_broadcast(&rw_cond); pthread_mutex_unlock(&cnt_mutex); } ~RWLock() { pthread_mutex_destroy(&cnt_mutex); pthread_cond_destroy(&rw_cond); } }; static RWLock lock; class Test { private : static void* shared_task_handler(void*) { while(1) { sleep(1); lock.get_shared_lock(); sleep(1); lock.release_shared_lock(); } return NULL; }
static void * exclusive_task_handler(void*) { while(1) { sleep(3); lock.get_exclusive_lock(); sleep(1); lock.release_exclusive_lock(); } return NULL; } public : typedef void* (*ThreadFunc) (void*); void start() { const int THREADS_NO=2; pthread_t* threads = new pthread_t[THREADS_NO]; int ret; volatile int i; for (i = 0; i < THREADS_NO; ++i) { ret = pthread_create(threads+i, NULL, shared_task_handler, NULL); if (ret != 0) { printf("pthread create_shared error=%d\n", ret); } } i = 100; ret = pthread_create(threads+i, NULL, exclusive_task_handler, NULL); if (ret != 0) { printf("pthread create_exclusive error=%d\n", ret); } } }; int main() { Test tmptest; tmptest.start(); while(1) { sleep(100); } }
|