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