在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。
处理读写着问题的两种常见策略是:强读者同步和强写者同步。在强读者同步过程中,总是给读者优先权,只要写着当前没有进行写操作,读者就可以获得访问权。在强写者同步过程中,通常将优先权先交给写者,而将读者延迟到所有等待的或者活动的写者都完成为止。简单的说:
(1)可以同时存在多个读操作
(2)写必须互斥(只允许一个写操作,不能读写操作同时进行)
(3)写操作优先于读操作,(一旦有写操作,后续的读操作必须等待,唤醒时有限考虑写操作)
下面是两种读写锁的使用示例.
一: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
阅读(787) | 评论(0) | 转发(0) |