您的位置:首页 > 运维架构 > Linux

Linux 下的线程读写锁

2012-10-12 11:23 288 查看

Linux 下的线程读写锁


有一种写优先读写锁,有如下特点:

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();

}

--------------------------

参考:

Solaris 執行緒與同步機制之實例

Posix线程编程指南
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: