线程的修炼3
来源:互联网 发布:电脑屏幕颜色校准软件 编辑:程序博客网 时间:2024/04/30 08:19
线程锁:因为多个线程共享相同的内存,所以需要确保每个线程看到一致的数据。如果数据是只读的,那么不存在一致性问题。但是如果线程对数据有读有写,此时需要同步机制来保证数据的一致性。需要一种机制确保变量修改时,只有一个线程在访问。这样就能保证数据的一致性。这时候就需要线程锁了。1.互斥量:用pthread_mutex_t mutex来定义一把锁.mutex是锁名。int pthread_mutex_init ( pthread_mutex_t *mutex, const pthread_mutexattr_t * attr );mutex为锁名的取地址,attr为属性,可以写NULL。关于上锁,解锁的3个函数:int pthread_mutex_lock(pthread_mutex_t *mutex);int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t*mutex);pthread_mutex_lock给互斥量mutex加锁。如果此互斥量已经加锁,那么调用该函数的线程会被阻塞;如果互斥量没加锁,调用线程给该互斥量加锁。Pthread_mutex_trylock尝试给互斥量mutex加锁,看锁是否能加上。 如果所能加上则返回0,不能加上则errno设置成EBUSY,错误返回其余值。pthread_mutex_unlock给互斥量解锁。成功返回0,失败返回非0.下面是一个用互斥量写的死锁:
#include <stdio.h>#include <pthread.h>pthread_mutex_t mutex1;pthread_mutex_t mutex2;void *thread1(void *arg){printf("thread1 trying to lock mutex1...\n");pthread_mutex_lock(&mutex1);printf("thread1 lock succeed mutex1...\n");sleep(5);printf("thread1 trying to lock mutex2...\n");pthread_mutex_lock(&mutex2);printf("thread1 try to unlock mutex1");pthread_mutex_unlock(&mutex1);printf("thread1 success to unlock mutex1...\n");}void *thread2(void* arg){printf("thread2 try to lock mutex2...\n");pthread_mutex_lock(&mutex2);printf("thread2 lock succeed mutex2...\n");sleep(5);printf("thread2 try to lock mutex1...\n");pthread_mutex_lock(&mutex1);printf("thread2 try to unlock mutex2");pthread_mutex_unlock(&mutex2);printf("thread2 success to unlock mutex2...\n");}int main(){int i;int num;pthread_t tid;pthread_attr_t attr;pthread_attr_init(&attr);pthread_mutex_init(&mutex1,NULL);pthread_mutex_init(&mutex2,NULL);pthread_create(&tid,&attr,thread1,NULL);pthread_create(&tid,&attr,thread2,NULL);getchar();}2.读写锁:
读写锁有三个状态:读锁、写锁、不加锁。同一时刻只有一个线程能拥有写锁,但是同一时刻可以有多个线程可以拥有读锁。
加了写锁后,任何线程都不能再加锁,无论读写。
加了读锁后,任何线程都可以对它加读锁,但不能加写锁。
读写锁适合读比较频繁,写比较少的情况,比如数据库。
用pthread_rwlock_t rwlock来定义一把锁.rwlock是锁名。
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr)
rwlock为锁名的取地址,attr为属性,可以写NULL。
当要释放读写锁时,必须先调用destroy函数:
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
加解读写锁函数:
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
加读锁时要注意判断返回值,因为加读锁的次数可能有限制!所以加读锁是会失败的。
加写锁无须判断返回值,写锁只能加一次。
无论加的是写锁还是读锁,都用pthread_rwlock_unlock解锁。
成功返回0,不成功返回非0
tryrdlock和trywrlock检查是否能加锁,能加锁返回0,不能加锁返回EBUSY,失败返回其余值。
#include#includepthread_rwlock_t rwlock; void *fun1(void *arg) { printf("thread1 try to lock rdlock\n"); pthread_rwlock_rdlock(&rwlock); printf("thread1 success to lock rdlock\n"); sleep(1); pthread_rwlock_unlock(&rwlock); printf("thread1 success to unlock\n"); sleep(1); printf("thread1 try to lock rdlock\n");pthread_rwlock_rdlock(&rwlock); printf("thread1 success to lock rdlock\n"); } void *fun2(void *arg) { printf("thread2 try to lock rdlock\n"); pthread_rwlock_rdlock(&rwlock); printf("thread2 success to lock rdlock\n"); sleep(1); pthread_rwlock_unlock(&rwlock); printf("thread2 success to unlock\n"); sleep(1); printf("thread2 try to lock rdlock\n"); pthread_rwlock_rdlock(&rwlock); printf("thread2 success to lock rdlock\n"); }void *fun3(void *arg){printf("thread3 try to lock wrlock\n"); pthread_rwlock_wrlock(&rwlock); printf("thread3 success to lock wrlock\n"); sleep(1); pthread_rwlock_unlock(&rwlock); printf("thread3 success to unlock\n"); }int main () { pthread_rwlock_init(&rwlock,NULL); pthread_t tid; pthread_create(&tid,NULL,fun1,NULL); pthread_create(&tid,NULL,fun2,NULL); pthread_create(&tid,NULL,fun3,NULL); getchar(); return 0; }条件锁:haimeixie
0 0
- 线程的修炼3
- 线程的修炼1
- 线程的修炼2
- java修炼线程并发
- 男人城府的修炼 男人成熟修炼
- 并发编程修炼一:进程和线程
- 并发编程修炼二:创建线程
- 看盘功夫的修炼
- 程序员的修炼法则
- Flash 修炼的书
- 气功修炼的原则
- 修炼的工具
- 胸怀的修炼
- 牛逼者-修炼的轨迹
- 牛逼者-修炼的轨迹
- 牛逼者-修炼的轨迹
- 程序员的修炼法则
- 修炼编程的内功
- 【Android 多媒体开发】 MediaPlayer 网络视频播放器
- 将登陆人ip写入txt文件
- 计算机网络【七】:可靠传输的实现
- Histogram equlization
- NSKeyedArchiver保存对象到本地
- 线程的修炼3
- 非常简短的linux脚本汇总
- 对象的深拷贝
- HDU 3127
- jsp九大内置对象
- [ACM] hdu 2262 Where is the canteen (高斯消元求期望)
- 天易35----mysql分页计算总页数公式
- easy_install工具的使用
- 计算机负数之表达