在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。
处理读写着问题的两种常见策略是:强读者同步和强写者同步在强读者同步过程中,总是给读者优先权,只要写着当前没有进行写操作,读者就可以获得访问权。在强写者同步过程中,通常将优先权先交给写者,而将读者延迟到所有等待的或者活动的写者都完成为止简单的说:
(1)可以同时存在多个读操作
(2)写必须互斥(只允许一个写操作,不能读写操作同时进行)
(3)写操作优先于读操作,(一旦有写操作,后续的读操作必须等待,唤醒时有限考虑写操作)
下面是两种读写锁的使用示例。
一:POSIX下的rw_lock
code:
#include < pthread 。h >
#include < cstdlib >
#include < ctime >
#include < iostream >
using namespace std ;
static int count = 0 ;
课堂考试
{
私人的 :
pthread_rwlock_t rwlock ;
static void * shared_task_handler ( void * arg )
{
Test * testptr = static_cast < Test * > ( arg );
pthread_rwlock_rdlock (& testptr - > rwlock );
/ / 做共享在这里的任务
COUT < < “读---计数=” < <计数< < ENDL ;
if ( pthread_rwlock_unlock (& testptr - > rwlock ) )
{
COUT < < “读解锁错误” < < ENDL ;
}
返回NULL ;
}
static void * exclusive_task_handler ( void * arg )
{
Test * testptr = static_cast < Test * > ( arg );
pthread_rwlock_wrlock (& testptr - > rwlock );
/ / 做专属任务在这里
+ +计数;
COUT < < “写-计数=” < <计数< < ENDL ;
if ( pthread_rwlock_unlock (& testptr - > rwlock ) )
{
COUT < < “写解锁错误” < < ENDL ;
}
返回NULL ;
}
公众 :
typedef void * (* ThreadFunc ) ( void * );
void start ()
{
srand (time (NULL ));
if ( pthread_rwlock_init (& rwlock ,NULL ) )
{
COUT < < “rwlock中初始化错误” < < 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失败” < < ENDL ;
退出( 1 );
}
}
rwlock中
for (int i = 0 ; i < THREADS_NO ; i + + )
{
pthread_join ( threads [ i ] ,NULL );
}
删除[ ]线程;
}
} ;
int main ()
{
测试tmptest ;
tmptest 。start ();
}
output:
book @ book -桌面:〜/分享$ 。/ posix_read_write_lock
写- - count = 1
写- -计数= 2
写- -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
写- -计数= 4
读- - - count = 4
写- -计数= 5
写- -计数= 6
读- - - count = 6
读- - - count = 6
读- - - count = 6
读- - - count = 6
写- -计数= 7
写- - count = 8
读- - - count = 8
读- - - count = 8
写- - count = 9
写- -计数= 10
读- - - count = 10
读- - - count = 10
读- - - count = 10
读- - - count = 10
读- - - count = 10
读- - - count = 10
读- - - count = 10
写- -计数= 11
写- -计数= 12
写- -计数= 13
写- -计数= 14
写- -计数= 15
读- - -计数= 15
二:利用pthread_cond_ *&pthread_mutex_ *实现rw_lock
code:
#include < pthread 。h >
#include < cstdlib >
#include < ctime >
#include < iostream >
using namespace std ;
RWLock 类
{
私人的 :
pthread_mutex_t cnt_mutex ;
pthread_cond_t rw_cond ;
int rd_cnt , wr_cnt ;
RWLock (const RWLock &);
RWLock & operator = (const RWLock &);
公众 :
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 );
而 ( 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 ;
课堂考试
{
私人的 :
RWLock锁;
static void * shared_task_handler ( void * arg )
{
Test * testptr = static_cast < Test * > ( arg );
testptr - >锁定。get_shared_lock ();
/ / 做共享在这里的任务
COUT < < “读---计数=” < <计数< < ENDL ;
testptr - >锁定。release_shared_lock ();
}
static void * exclusive_task_handler ( void * arg )
{
Test * testptr = static_cast < Test * > ( arg );
testptr - >锁定。get_exclusive_lock ();
/ / 做专属任务在这里
+ +计数;
COUT < < “写-计数=” < <计数< < ENDL ;
testptr - >锁定。release_exclusive_lock ();
}
公众 :
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失败” < < ENDL ;
退出( 1 );
}
}
for (int i = 0 ; i < THREADS_NO ; i + + )
{
pthread_join ( threads [ i ] ,NULL );
}
删除[ ]线程;
}
} ;
int main ()
{
测试tmptest ;
tmptest 。start ();
}
output:
book @ book -桌面:〜/分享$ 。/ read_write_lock
读- - - count = 0
读- - - count = 0
读- - - count = 0
写- - count = 1
读- - - count = 1
读- - - count = 1
读- - - count = 1
读- - - count = 1
写- -计数= 2
写- -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
读- - -计数= 3
写- -计数= 4
写- -计数= 5
写- -计数= 6
写- -计数= 7
写- - count = 8
写- - count = 9
写- -计数= 10
写- -计数= 11
读- - -计数= 11
写- -计数= 12
写- -计数= 13
读- - - count = 13
读- - - count = 13
写- -计数= 14
写- -计数= 15
写- -计数= 16
写- -计数= 17
写- -计数= 18
写- -计数= 19
读- - - count = 19
写- -计数= 20
读- - -计数= 20
写- -计数= 21
读- - -计数= 21
写- -计数= 22
读- - -计数= 22
读- - -计数= 22
写- -计数= 23
读- - -计数= 23
读- - -计数= 23
读- - -计数= 23
写- -计数= 24
读- - -计数= 24
写- -计数= 25
写- -计数= 26
写- -计数= 27
写- -计数= 28
读- - -计数= 28
读- - -计数= 28
写- -计数= 29
写- -计数= 30
读- - -计数= 30
读- - -计数= 30
读- - -计数= 30
写- -计数= 31
读- - -计数= 31
读- - -计数= 31
写- -计数= 32
读- - -计数= 32
写- -计数= 33
读- - -计数= 33
读- - -计数= 33
读- - -计数= 33
读- - -计数= 33
读- - -计数= 33
写- -计数= 34
写- -计数= 35