在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。
处理读写着问题的两种常见策略是:强读者同步和强写者同步。在强读者同步过程中,总是给读者优先权,只要写着当前没有进行写操作,读者就可以获得访问权。在强写者同步过程中,通常将优先权先交给写者,而将读者延迟到所有等待的或者活动的写者都完成为止。简单的说:
(1)可以同时存在多个读操作
(2)写必须互斥(只允许一个写操作,不能读写操作同时进行)
(3)写操作优先于读操作,(一旦有写操作,后续的读操作必须等待,唤醒时有限考虑写操作)
下面是两种读写锁的使用示例.
一:POSIX 下的rw_lock
output:
二:利用pthread_cond_* & pthread_mutex_* 实现rw_lock
output:
参考:
一:POSIX 下的rw_lock
点击(此处)折叠或打开
- #include pthread.h>
- #include cstdlib>
- #include ctime>
- #include iostream>
- using namespace std;
-
- static int count = 0;
- class Test
- {
- private :
- pthread_rwlock_t rwlock;
-
- static void* shared_task_handler(void* arg)
- {
- Test* testptr = static_castTest*>(arg);
- pthread_rwlock_rdlock(&testptr->rwlock);
- // do the shared task here
- cout "read---count = " count endl;
- if (pthread_rwlock_unlock(&testptr->rwlock) )
- {
- cout "read unlock error " endl;
- }
- return NULL;
- }
-
- static void * exclusive_task_handler(void * arg)
- {
- Test* testptr = static_castTest*>(arg);
- pthread_rwlock_wrlock(&testptr->rwlock);
- //do the exclusive task here
- ++count;
- cout "write--count = " count endl;
- if (pthread_rwlock_unlock(&testptr->rwlock) )
- {
- cout "write unlock error " endl;
- }
- return NULL;
- }
-
- public :
- typedef void* (*ThreadFunc) (void*);
- void start()
- {
- srand(time(NULL));
-
- if( pthread_rwlock_init(&rwlock,NULL) )
- {
- cout "rwlock init error " endl;
- }
-
- 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);
- }
- }
- rwlock
- for(int i=0; iTHREADS_NO; i++)
- {
- pthread_join(threads[i],NULL);
- }
- delete[] threads;
- }
- };
-
- int main()
- {
- Test tmptest;
- tmptest.start();
- }
output:
点击(此处)折叠或打开
- lee@lee-desktop:~/share$ ./posix_read_write_lock
- write--count = 1
- write--count = 2
- write--count = 3
- read---count = 3
- read---count = 3
- read---count = 3
- read---count = 3
- write--count = 4
- read---count = 4
- write--count = 5
- write--count = 6
- read---count = 6
- read---count = 6
- read---count = 6
- read---count = 6
- write--count = 7
- write--count = 8
- read---count = 8
- read---count = 8
- write--count = 9
- write--count = 10
- read---count = 10
- read---count = 10
- read---count = 10
- read---count = 10
- read---count = 10
- read---count = 10
- read---count = 10
- write--count = 11
- write--count = 12
- write--count = 13
- write--count = 14
- write--count = 15
- read---count = 15
二:利用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);
- }
- };
-
- static int count = 0;
- class Test
- {
- private :
- RWLock lock;
-
- static void* shared_task_handler(void* arg)
- {
- Test* testptr = static_castTest*>(arg);
- testptr->lock.get_shared_lock();
- // do the shared task here
- cout "read---count = " count endl;
- testptr->lock.release_shared_lock();
- }
-
- static void * exclusive_task_handler(void * arg)
- {
- Test* testptr = static_castTest*>(arg);
- testptr->lock.get_exclusive_lock();
- //do the exclusive task here
- ++count;
- cout "write--count = " count endl;
- 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; iTHREADS_NO; i++)
- {
- pthread_join(threads[i],NULL);
- }
-
- delete[] threads;
- }
- };
-
- int main()
- {
- Test tmptest;
- tmptest.start();
- }
output:
点击(此处)折叠或打开
lee@lee-desktop:~/share$ ./read_write_lock
read---count = 0
read---count = 0
read---count = 0
write--count = 1
read---count = 1
read---count = 1
read---count = 1
read---count = 1
write--count = 2
write--count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
write--count = 4
write--count = 5
write--count = 6
write--count = 7
write--count = 8
write--count = 9
write--count = 10
write--count = 11
read---count = 11
write--count = 12
write--count = 13
read---count = 13
read---count = 13
write--count = 14
write--count = 15
write--count = 16
write--count = 17
write--count = 18
write--count = 19
read---count = 19
write--count = 20
read---count = 20
write--count = 21
read---count = 21
write--count = 22
read---count = 22
read---count = 22
write--count = 23
read---count = 23
read---count = 23
read---count = 23
write--count = 24
read---count = 24
write--count = 25
write--count = 26
write--count = 27
write--count = 28
read---count = 28
read---count = 28
write--count = 29
write--count = 30
read---count = 30
read---count = 30
read---count = 30
write--count = 31
read---count = 31
read---count = 31
write--count = 32
read---count = 32
write--count = 33
read---count = 33
read---count = 33
read---count = 33
read---count = 33
read---count = 33
write--count = 34
write--count = 35
read---count = 0
read---count = 0
read---count = 0
write--count = 1
read---count = 1
read---count = 1
read---count = 1
read---count = 1
write--count = 2
write--count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
read---count = 3
write--count = 4
write--count = 5
write--count = 6
write--count = 7
write--count = 8
write--count = 9
write--count = 10
write--count = 11
read---count = 11
write--count = 12
write--count = 13
read---count = 13
read---count = 13
write--count = 14
write--count = 15
write--count = 16
write--count = 17
write--count = 18
write--count = 19
read---count = 19
write--count = 20
read---count = 20
write--count = 21
read---count = 21
write--count = 22
read---count = 22
read---count = 22
write--count = 23
read---count = 23
read---count = 23
read---count = 23
write--count = 24
read---count = 24
write--count = 25
write--count = 26
write--count = 27
write--count = 28
read---count = 28
read---count = 28
write--count = 29
write--count = 30
read---count = 30
read---count = 30
read---count = 30
write--count = 31
read---count = 31
read---count = 31
write--count = 32
read---count = 32
write--count = 33
read---count = 33
read---count = 33
read---count = 33
read---count = 33
read---count = 33
write--count = 34
write--count = 35
参考:
http://www.cppblog.com/bigsml/archive/2006/09/07/12137.html