一个写优先的读写锁实现


/* g++ -Wall -o rwlock rwlock.cpp -lpthread
*
* 一个写优先读写锁的实现,多线程频繁读,多线程少量写,同时写优先,性能极佳。
* 当写锁(独占锁)lock成功的必要条件是:
* 1. 将写锁计数++;
* 2. 会阻塞后续对读锁(共享锁)的读;
* 3. 等待读锁的计数为0;
* 4. 等待写锁的计数为1;
*
*/
#include
#include
#include
#include
#include
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_t tag = pthread_self ();
pthread_mutex_lock (& cnt_mutex );
rd_cnt ++;
time_t now = time ( NULL );
printf ( "[%lu]r_lock[thread_0x%x] r=%d w=%d\n" , now , ( int ) tag , rd_cnt , wr_cnt );
while ( wr_cnt > 0 )
{
printf ( "\t\t r_lock wait for wr_cnt[%d]\n" , wr_cnt );
pthread_cond_wait (& rw_cond ,& cnt_mutex );
}
pthread_mutex_unlock (& cnt_mutex );
}
void release_shared_lock ()
{
pthread_t tag = pthread_self ();
pthread_mutex_lock (& cnt_mutex );
rd_cnt --;
time_t now = time ( NULL );
printf ( "[%lu]r_unlock[thread_0x%x] r=%d w=%d\n" , now , ( int ) tag , rd_cnt , wr_cnt );
if ( 0 == rd_cnt )
{
printf ( "\t\t r_unlock[thread_0x%x] rd_cnt=0, so singal to wr_cnt[%d]\n" , ( int ) tag , wr_cnt );
pthread_cond_signal (& rw_cond );
}
pthread_mutex_unlock (& cnt_mutex );
}
void get_exclusive_lock ()
{
pthread_t tag = pthread_self ();
pthread_mutex_lock (& cnt_mutex );
wr_cnt ++;
time_t now = time ( NULL );
printf ( "=====[%lu]w_lock[thread_0x%x] r=%d w=%d\n" , now , ( int ) tag , rd_cnt , wr_cnt );
while ( rd_cnt + wr_cnt >= 2 )
{
printf ( "\t\t w_lock wait r=%d w=%d\n" , rd_cnt , wr_cnt );
pthread_cond_wait (& rw_cond ,& cnt_mutex );
}
printf ( "=====\t\t w_lock[thread_0x%x] get ok r=%d w=%d\n" , ( int ) tag , rd_cnt , wr_cnt );
pthread_mutex_unlock (& cnt_mutex );
}
void release_exclusive_lock ()
{
pthread_t tag = pthread_self ();
pthread_mutex_lock (& cnt_mutex );
wr_cnt --;
time_t now = time ( NULL );
printf ( "=====[%lu]w_unlock[thread_0x%x] r=%d w=%d, then broadcast\n" , now , ( int ) tag , rd_cnt , wr_cnt );
pthread_cond_broadcast (& rw_cond );
pthread_mutex_unlock (& cnt_mutex );
}
~ RWLock ()
{
pthread_mutex_destroy (& cnt_mutex );
pthread_cond_destroy (& rw_cond );
}
};
static RWLock lock ;
class Test
{
private :
static void * shared_task_handler ( void *)
{
while ( 1 )
{
sleep ( 1 );
lock . get_shared_lock ();
sleep ( 1 );
lock . release_shared_lock ();
}
return NULL ;
}

static void * exclusive_task_handler ( void *)
{
while ( 1 )
{
sleep ( 3 );
lock . get_exclusive_lock ();
sleep ( 1 );
lock . release_exclusive_lock ();
}
return NULL ;
}
public :
typedef void * (* ThreadFunc ) ( void *);
void start ()
{
const int THREADS_NO = 2 ;
pthread_t * threads = new pthread_t [ THREADS_NO ];
int ret ;
volatile int i ;
for ( i = 0 ; i < THREADS_NO ; ++ i )
{
ret = pthread_create ( threads + i , NULL , shared_task_handler , NULL );
if ( ret != 0 )
{
printf ( "pthread create_shared error=%d\n" , ret );
}
}
i = 100 ;
ret = pthread_create ( threads + i , NULL , exclusive_task_handler , NULL );
if ( ret != 0 )
{
printf ( "pthread create_exclusive error=%d\n" , ret );
}
}
};
int main ()
{
Test tmptest ;
tmptest . start ();
while ( 1 )
{
sleep ( 100 );
}
}

运行结果:

[ 1257927661 ] r_lock [ thread_0xb7c9fba0 ] r = 1 w = 0
[ 1257927661 ] r_lock [ thread_0xb749eba0 ] r = 2 w = 0
[ 1257927662 ] r_unlock [ thread_0xb7c9fba0 ] r = 1 w = 0
[ 1257927662 ] r_unlock [ thread_0xb749eba0 ] r = 0 w = 0
r_unlock [ thread_0xb749eba0 ] rd_cnt = 0 , so singal to wr_cnt [ 0 ]
=====[ 1257927663 ] w_lock [ thread_0xb6c9dba0 ] r = 0 w = 1
===== w_lock [ thread_0xb6c9dba0 ] get ok r = 0 w = 1
[ 1257927663 ] r_lock [ thread_0xb749eba0 ] r = 1 w = 1
r_lock wait for wr_cnt [ 1 ]
[ 1257927663 ] r_lock [ thread_0xb7c9fba0 ] r = 2 w = 1
r_lock wait for wr_cnt [ 1 ]
=====[ 1257927664 ] w_unlock [ thread_0xb6c9dba0 ] r = 2 w = 0 , then broadcast
[ 1257927665 ] r_unlock [ thread_0xb749eba0 ] r = 1 w = 0
[ 1257927665 ] r_unlock [ thread_0xb7c9fba0 ] r = 0 w = 0
r_unlock [ thread_0xb7c9fba0 ] rd_cnt = 0 , so singal to wr_cnt [ 0 ]
[ 1257927666 ] r_lock [ thread_0xb749eba0 ] r = 1 w = 0
[ 1257927666 ] r_lock [ thread_0xb7c9fba0 ] r = 2 w = 0

你可能感兴趣的:(C++,linux~,操作系统)