线程读写锁总结
概括:pthread_wrlock 线程读写锁用于多线程的异步控制,主要是用于并发控制;
主要接口函数
接口名 | 入参 | 出参 | 备注 |
---|---|---|---|
int pthread_rwlock_rdlock | 锁句柄指针 | 执行结果 | 读加锁 |
int pthread_rwlock_wrlock | 锁句柄指针 | 执行结果 | 写加锁 |
int pthread_rwlock_unlock | 锁句柄指针 | 执行结果 | 解锁 |
int pthread_rwlock_tryrdlock | 锁句柄 | 执行结果 | 尝试获取读锁 |
int pthread_rwlock_trywrlock | 锁句柄指针 | 执行结果 | 尝试获取写锁 |
int pthread_rwlock_init | 锁句柄 | 执行结果 | 默认锁初始化,也可以使用宏直接赋值(PTHREAD_RWLOCK_INITIALIZER) |
int pthread_rwlock_destroy | 锁句柄 | 执行结果 | 销毁回收锁资源 |
通常情况代码示例:
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
void * func_1(void *arg)
{
int iRet = 0;
iRet = pthread_rwlock_wrlock(&rwlock);
sleep(1);
puts("Hi, i get rwlock");
if (0 == iRet)
{
pthread_rwlock_unlock(&rwlock);
puts("Hi, i free rwlock");
}
}
int main(void)
{
pthread_t astPthread[10];
int iPthreadNum = 2;
int i;
for ( i = 0; i < iPthreadNum; i++)
{
pthread_create(&astPthread[i], NULL, func_1, NULL);
}
for (i = 0; i < iPthreadNum; i++)
{
pthread_join(astPthread[i], NULL);
}
}
一把写锁和多把读锁的关系;
读锁在开门的时候需要看看写锁是否插入如果当前写锁在用着,需要阻塞;如果没有写锁在,多把读锁都可以获取;
如果要获取写锁,就要看看当前有没有写锁,如果有,将阻塞直到释放;如果没有,那么看看是否有读锁在,如果有,那么依旧等待阻塞;等读锁释放之后,再获取写锁;
<bits/pthreadtype.h>
typedef union
{
# if __WORDSIZE == 64
struct
{
int __lock;
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
int __writer;
int __shared;
unsigned long int __pad1;
unsigned long int __pad2;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned int __flags;
} __data;
# else
struct
{
int __lock;
unsigned int __nr_readers;
unsigned int __readers_wakeup;
unsigned int __writer_wakeup;
unsigned int __nr_readers_queued;
unsigned int __nr_writers_queued;
/* FLAGS must stay at this position in the structure to maintain
binary compatibility. */
unsigned char __flags;
unsigned char __shared;
unsigned char __pad1;
unsigned char __pad2;
int __writer;
} __data;
# endif
char __size[__SIZEOF_PTHREAD_RWLOCK_T];
long int __align;
} pthread_rwlock_t;
void * func_1(void *arg)
{
int iRet = 0;
iRet = pthread_rwlock_rdlock(&rwlock);
sleep(2);
puts("Hi, i get rdlock");
printf ("reader:%d\n", rwlock.__data.__nr_readers);
if (0 == iRet)
{
pthread_rwlock_unlock(&rwlock);
puts("Hi, i free rdlock");
printf ("reader:%d\n", rwlock.__data.__nr_readers);
}
pthread_rwlock_unlock(&rwlock);
puts("Hi, i free rdlock again");
printf ("reader:%d\n", rwlock.__data.__nr_readers);
}
void * func_2(void *arg)
{
int iRet = 0;
iRet = pthread_rwlock_wrlock(&rwlock);
sleep(2);
puts("Hi, i get wrlock");
printf ("reader:%d\n", rwlock.__data.__nr_readers);
printf ("writer:%d\n", rwlock.__data.__writer);
if (0 == iRet)
{
pthread_rwlock_unlock(&rwlock);
puts("Hi, i free wrlock");
}
}
root@desktop:pthreadlock# ./main -lpthread
Hi, i get rdlock
reader:1
Hi, i free rdlock
reader:0
Hi, i free rdlock again <--- 错误释放锁
reader:-1 <--- 读锁使用者异常
^C <-- 获取写锁错误阻塞
如果当前线程已经加了写锁,然后再加上读锁会如何:
pthread_rwlock_t rwl;
cout << "init: " << pthread_rwlock_init(&rwl, NULL) << endl;
cout << "wrlock: " << pthread_rwlock_wrlock(&rwl) << endl;
cout << "rdlock: " << pthread_rwlock_rdlock(&rwl) << endl;
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;
cout << "wrlock: " << pthread_rwlock_wrlock(&rwl) << endl; // DEAD!
cout << "unlock: " << pthread_rwlock_unlock(&rwl) << endl;
输出为:
init: 0
wrlock: 0
rdlock: 35
//#define EDEADLK 35 /* Resource deadlock would occur */
unlock: 0
unlock: 0
结论:需要判断加锁返回值,确保加锁解锁安全;
参考:
http://www-numi.fnal.gov/offline_software/srt_public_context/WebDocs/Errors/unix_system_errors.html
http://blog.csdn.net/jq0123/article/details/3297211
http://www.cnblogs.com/diegodu/p/3890450.html