在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。
处理读写着问题的两种常见策略是:强读者同步和强写者同步。在强读者同步过程中,总是给读者优先权,只要写着当前没有进行写操作,读者就可以获得访问权。在强写者同步过程中,通常将优先权先交给写者,而将读者延迟到所有等待的或者活动的写者都完成为止。简单的说:
(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_cast<Test*>(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_cast<Test*>(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; i<THREADS_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_cast<Test*>(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_cast<Test*>(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; i<THREADS_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
参考:
http://www.cppblog.com/bigsml/archive/2006/09/07/12137.html