有一种写优先读写锁,有如下特点:
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
在Solaris 中直接提供了读写锁, 但是在Linux 中只提供了线程的读写锁, 这里记录了一些读写锁的资料.
1.Solaris .vs. Linux Posix 库函数
2.使用mutex 来实现
设置三个互斥信号量:
rwmutex 用于写者与其他读者/写者互斥的访问共享数据
rmutex 用于读者互斥的访问读者计数器readcount
nrmutex 用于写者等待已进入读者退出,所有读者退出前互斥写操作
var rwmutex,rmutex,nrmutex:semaphore:=1,1,1;
int readcount=0;
cobegin
reader begin
P(rwmutex);
P(rmutex);
readcount++;
if (readcount == 1) P(nrmutex); //有读者进入,互斥写操作
V(rmutex);
V(rwmutex); //及时释放读写互斥信号量,允许其它读、写进程申请资源读数据;
P(rmutex);
readcount--;
if(readcount == 0) V(nrmutex); //所有读者退出,允许写更新
V(rmutex);
End
writer begin
P(rwmutex); //互斥后续其它读者、写者
P(nrmutex); //如有读者正在读,等待所有读者读完
写更新;
V(nrmutex); //允许后续新的第一个读者进入后互斥写操作
V(rwmutex); //允许后续新读者及其它写者
End
coend
3. 利用pthread_cond_* & pthread_mutex_* 实现rw_lock
--------------------------
参考:
Solaris 執行緒與同步機制之實例
Posix线程编程指南
1)多个读者可以同时进行读
2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)
3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)
在Solaris 中直接提供了读写锁, 但是在Linux 中只提供了线程的读写锁, 这里记录了一些读写锁的资料.
1.Solaris .vs. Linux Posix 库函数
Solaris 库(lib 线程) | Linux POSIX 库(libp 线程) | 操作 |
sema_destroy() | sem_destroy() | 销毁信号状态。 |
sema_init() | sem_init() | 初始化信号。 |
sema_post() | sem_post() | 增加信号。 |
sema_wait() | sem_wait() | 阻止信号计数。 |
sema_trywait() | sem_trywait() | 减少信号计数。 |
mutex_destroy() | pthread_mutex_destroy() | 销毁或禁用与互斥对象相关的状态。 |
mutex_init() | pthread_mutex_init() | 初始化互斥变量。 |
mutex_lock() | pthread_mutex_lock() | 锁定互斥对象和块,直到互斥对象被释放。 |
mutex_unlock() | pthread_mutex_unlock() | 释放互斥对象。 |
cond_broadcast() | pthread_cond_broadcast() | 解除对等待条件变量的所有线程的阻塞。 |
cond_destroy() | pthread_cond_destroy() | 销毁与条件变量相关的任何状态。 |
cond_init() | pthread_cond_init() | 初始化条件变量。 |
cond_signal() | pthread_cond_signal() | 解除等待条件变量的下一个线程的阻塞。 |
cond_wait() | pthread_cond_wait() | 阻止条件变量,并在最后释放它。 |
rwlock_init() | pthread_rwlock_init() | 初始化读/写锁。 |
rwlock_destroy() | pthread_rwlock_destroy() | 锁定读/写锁。 |
rw_rdlock() | pthread_rwlock_rdlock() | 读取读/写锁上的锁。 |
rw_wrlock() | pthread_rwlock_wrlock() | 写读/写锁上的锁。 |
rw_unlock() | pthread_rwlock_unlock() | 解除读/写锁。 |
rw_tryrdlock() | pthread_rwlock_tryrdlock() | 读取非阻塞读/写锁上的锁。 |
rw_trywrlock() | pthread_rwlock_trywrlock() | 写非阻塞读/写锁上的锁。 |
2.使用mutex 来实现
设置三个互斥信号量:
rwmutex 用于写者与其他读者/写者互斥的访问共享数据
rmutex 用于读者互斥的访问读者计数器readcount
nrmutex 用于写者等待已进入读者退出,所有读者退出前互斥写操作
var rwmutex,rmutex,nrmutex:semaphore:=1,1,1;
int readcount=0;
cobegin
reader begin
P(rwmutex);
P(rmutex);
readcount++;
if (readcount == 1) P(nrmutex); //有读者进入,互斥写操作
V(rmutex);
V(rwmutex); //及时释放读写互斥信号量,允许其它读、写进程申请资源读数据;
P(rmutex);
readcount--;
if(readcount == 0) V(nrmutex); //所有读者退出,允许写更新
V(rmutex);
End
writer begin
P(rwmutex); //互斥后续其它读者、写者
P(nrmutex); //如有读者正在读,等待所有读者读完
写更新;
V(nrmutex); //允许后续新的第一个读者进入后互斥写操作
V(rwmutex); //允许后续新读者及其它写者
End
coend
3. 利用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);
}
};
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
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
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();
}
#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);
}
};
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
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
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();
}
--------------------------
参考:
Solaris 執行緒與同步機制之實例
Posix线程编程指南