进程通信之读写锁
来源:互联网 发布:可靠性软件招标2016 编辑:程序博客网 时间:2024/06/06 05:10
读写锁
读写锁的分配规则
1. 没有线程持有读写锁进行写,任意数量的线程可以持有该读写锁用于读
2. 只有没有线程持有给定的读写锁用于读或者写的时候,才能分配读写锁用于写。
如果修改数据频繁,那么可以考虑用读写锁替代互斥锁。
获取与释放
- 如果对应的读写锁已由某个写入者持有,那么阻塞pthread_rwlock_rdlock获取读出锁
- 如果对应的读写锁已由另一个写入者持有,那就阻塞pthread_rwlock_wrlock获取写入锁。
- pthread_rwlock_unlock用于释放读出锁或者写入锁。
三者成功时返回0,出错时返回正的错误值 - pthread_rwlock_tryrdlock(pthread _rwlock_t *rwptr)尝试获取读出锁,如果不能马上获得,返回EBUSY错误。
- pthread_rwlock_trywrlock(pthread _rwlock_t *rwptr)尝试获取写入锁,如果不能马上获得,返回EBUSY错误。
初始化和摧毁
- 动态初始化
int pthread_rwlock_init(pthread_rwlock_t *rwptr, const pthread_rwlockattr_t *attr)
- 静态初始化
PTHREAD_RWLOCK_INITIALIZER
- 摧毁
int pthread_rwlock_destroy(pthread_rwlock_t *rwptr)
属性设置
int pthread_rwlockattr_init(pthread_rwlockattr_t * attr)int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr)int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * attr,int *valptr)int pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr,int val)
读写锁很适合读的次数远大于写的次数的情况。
例子: 一个写者,多个读者。用读写锁进行协调工作。
code:
#include <pthread.h>#include <stdio.h>#include <stdlib.h>#include <string.h>struct data{ int number; char info[105];};struct data *pdata = NULL; pthread_rwlock_t lock;void *read(void *arg){ int id = *((int *)arg); while(1){ int ret; ret = pthread_rwlock_tryrdlock(&lock); if(ret != 0) continue; printf("reader %d is reading!\n",id); if(pdata == NULL) printf("data is null.\n"); else printf("data: number is %d, info are %s.\n",pdata->number,pdata->info); pthread_rwlock_unlock(&lock); } pthread_exit(0);}void *write(void *arg){ int id = *((int *)arg); while(1){ int ret; ret = pthread_rwlock_trywrlock(&lock); if(ret !=0) continue; printf("writer %d is writing!\n",id); if(pdata == NULL){ pdata = (struct data *)malloc(sizeof(struct data)); pdata->number = 1; strcpy(pdata->info,"I love linux."); printf("finish, wrote it.\n"); } else printf("the pdata is not null.\n"); pthread_rwlock_unlock(&lock); } pthread_exit(0);}int main(){ pthread_t reader[10]; pthread_t writer; int i; pthread_create(&writer,NULL,write,(void *)&i); for(i=0; i<10; i++){ pthread_create(&reader[i],NULL,read,(void *)&i); } //pthread_create(&writer,NULL,write,NULL); if(pdata != NULL) free(pdata); getchar(); return 0;}
运行:
writer 1 is writing!finish, wrote it.reader 2 is reading!data: number is 1, info are I love linux..writer 1 is writing!the pdata is not null.reader 2 is reading!data: number is 1, info are I love linux..reader 2 is reading!data: number is 1, info are I love linux..
线程取消函数: int pthread_cancel(pthread_t tid)
一个线程可以被同一进程中的其他线程取消。
与之对应的自愿终止: void pthread_exit(void *retval)
#include <stdio.h>#include <unistd.h>#include "unix98.h"#include <pthread.h>pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;pthread_t tid1, tid2;void *thread1(void *), *thread2(void *);int main(){ pthread_setconcurrency(2); pthread_create(&tid1,NULL,thread1,NULL); sleep(1); /* let tid2 get lock. */ pthread_create(&tid2,NULL,thread2,NULL); void *status; /* store returned value from waited tid */ pthread_join(tid2,&status); if(status != PTHREAD_CANCELED){ printf("thread2 status = %p \n", status); } pthread_join(tid1, &status); if(status != NULL){ printf("thread1 status = %p\n",status); } //printf("rw_refcount = %d, rw_nwaitreaders = %d, rw_nwaitwriter = %d\n", // rwlock.rw_refcount,rwlock.rw_nwaitreaders, rwlock.rw_nwaitwriters); pthread_rwlock_destroy(&rwlock); return 0;}void *thread1(void *arg){ pthread_rwlock_rdlock(&rwlock); printf("thread1 got a read lock.\n"); sleep(3); /* let thread2 block in pthread_rwlock_wrlock */ pthread_cancel(tid2); sleep(3); pthread_rwlock_unlock(&rwlock); return NULL;}void *thread2(void *arg){ printf("thread2 try to obtain a write lock.\n"); pthread_rwlock_wrlock(&rwlock); printf("thread2() get a write lock.\n"); sleep(1); pthread_rwlock_unlock(&rwlock); return NULL;}
./pthread_cancel thread1 got a read lock.thread2 try to obtain a write lock.thread2() get a write lock.
fcntl函数和读写锁
文件锁:建议性锁,强制性锁
lock结构体:
Struct flock{short l_type;off_t l_start;short l_whence;off_t l_len;pid_t l_pid;}
flock可施加建议性锁,fcntl既可以施加建议性锁,也可施加强制性锁。
fcntl也可以对某一记录进行上锁,也就是所谓的记录锁。记录锁分为读取锁(共享锁),写入锁(排斥锁,互斥锁)。
fcntl建立记录锁:
下面是一个学习的例子,参考 http://www.jb51.net/article/37671.htm
使用fcntl增加和释放锁:
#include <unistd.h>#include <sys/types.h>#include <fcntl.h>#include <stdio.h>#include <sys/stat.h>#include <stdlib.h>void lock_set(int fd,int type){ struct flock lock; lock.l_whence = SEEK_SET; /* 相对位移量的起点是文件的开头 */ lock.l_start = 0; /* 相对位移量 */ lock.l_len = 0; /* 加锁区域的长度 */ while(1){ lock.l_type=type; if(fcntl(fd,F_SETLK,&lock) == 0){ if(lock.l_type == F_RDLCK) printf("read lock by %d\n", getpid()); else if(lock.l_type == F_WRLCK) printf("write lock by %d\n", getpid()); else if(lock.l_type == F_UNLCK) printf("release lock by %d\n", getpid()); return ; } fcntl(fd,F_GETLK,&lock); if(lock.l_type != F_UNLCK){ if(lock.l_type == F_RDLCK) printf("read lock already set by %d\n",lock.l_pid); else if(lock.l_type == F_WRLCK) printf("write lock already set by %d\n",lock.l_pid); printf("please enter any key to continue: "); getchar(); } }}int main(){ int fd = open("path",O_RDWR | O_CREAT, 0755); /* 当前路径下创建path */ if(fd == -1){ perror("open: "); exit(1); } lock_set(fd,F_WRLCK); puts("wait for a secend...\n"); sleep(6); lock_set(fd,F_UNLCK); puts("wait for a secend...\n"); sleep(1); close(fd); exit(0);}
不修改上面的代码,试试写入锁 + 写入锁, 看看效果。
在不同的标签内运行此程序:
write + write
./writewrite lock by 2904wait for a secend...release lock by 2904wait for a secend..../writewrite lock already set by 2904please enter any key to continue: write lock already set by 2904please enter any key to continue: write lock by 2905wait for a secend...release lock by 2905wait for a secend...
在已有write锁的情况下不能加上write锁。
现在,稍作修改
lock_set(fd,F_WRLCK);--->lock_set(fd,F_RDLCK);
write + read
./write write lock by 3005wait for a secend...release lock by 3005wait for a secend..../read write lock already set by 3005please enter any key to continue: write lock already set by 3005please enter any key to continue: write lock already set by 3005please enter any key to continue: read lock by 3006wait for a secend...release lock by 3006wait for a secend...
在已有write锁的情况下不能加上read锁
read + write
./read read lock by 3019wait for a secend...release lock by 3019wait for a secend..../write read lock already set by 3019please enter any key to continue: read lock already set by 3019please enter any key to continue: read lock already set by 3019please enter any key to continue: read lock already set by 3019please enter any key to continue: write lock by 3020wait for a secend...release lock by 3020wait for a secend...
在已有read锁的情况下不能加上write锁
read + read
./readread lock by 3035wait for a secend...release lock by 3035wait for a secend..../read read lock by 3036wait for a secend...release lock by 3036wait for a secend...
read锁和read锁不冲突。在已有read锁的情况下可以加上read锁。
0 0
- 进程通信之读写锁
- 进程通信之文件读写
- Windows进程通信之进程内存读写
- 进程通信学习笔记(读写锁)
- 15章 进程间通信之同步(互斥锁、条件变量、读写锁、信号量)
- 通过互斥量和读写锁来实现进程间通信
- 进程间通信学习笔记-互斥锁 && 读写锁
- 线程通信机制之轻量级读写锁
- 进程通信之管道通信
- 进程通信之信号通信
- 进程通信之管道通信
- 进程通信之管道通信
- 进程通信之pipe通信
- 【进程通信】之管道通信
- 进程通信之协同进程
- 内存读写函数实现进程间通信
- [进程通信] 进程间通信 之 管道
- 进程通信实例之父子进程通信
- Android系统的常用权限整理
- C#与C++混合编程之引用(一)
- Python(六)函数
- Android studio导入依赖项目
- 越是复杂的界面越是要进行封装
- 进程通信之读写锁
- javascript中的数组方法
- C++ 学习一之用vs2015的使用常识
- 判断两个区间范围是否重复
- Linux命令行模式修改语言&菱形乱码解决方法
- LayerAnchorPoint
- 3-3 构造函数的调用(高级)
- Fragment基本使用(二)——动态加载
- Android之在IntentService中执行后台程序