线程互斥实现方式
1. 互斥锁
2. 读写硕
3. 线程信号量
互斥锁:
互斥锁的数据类型:pthread_mutex_t
互斥锁是一种加锁的方法来控制对共享资源的访问。同一时刻只能由一个线程掌握某个互斥锁(就是有一把互斥锁),一个线程对共享资源上锁了,其他线程希望上锁一个已经上了互 斥锁的共享资源,那么这些线程将会阻塞,直到上锁的线程释放互斥锁为止。
通俗的解释就是:某个线程对共享资源上了某把互斥锁,其他线程想重新用这把互斥锁上锁,那这些线程将会阻塞,直到上锁的线程将这把互斥锁释放为止。
在一个线程中加锁,在另一个线程中解锁可以成功(有这种情况)。
互斥锁的创建和销毁:
参数:
mutex:要创建的那把互斥锁(互斥锁可以创建多把)
mutexattr:互斥锁创建方式
上锁和解锁:
互斥锁的整体使用流程:
1. 创建互斥锁
2. 对共享资源枷锁
3. 对共享资源解锁
4. 释放互斥锁
注意:一把互斥锁就和某个共享资源绑定。如果有多个共享资源,可以定义多把互斥锁。建议不要把互斥锁定义为全局变量。
互斥锁属性创建和销毁:
互斥锁也有很多属性,和线程一样,都有一个结构来定义这些属性(pthread_mutexattr_t),如进程共享属性、互斥锁的类型
互斥锁进程共享属性:
互斥锁的类型:
读写硕:
为什么会用读写硕?
以为使用互斥锁缺乏读的并发性。即当多个线程对共享资源读时(没有修改共享资源的数据),只有一个线程可以读,其他线程只能阻塞。
读写锁就能解决这种问题,当读(不修改共享资源数据)操作较多,写(要修改共享资源数据)操作较少时,使用读写锁提高线程的读的并发性。
读写锁的数据类型:pthread_rwlock_t
读写锁也是只有一把锁,但是它有两种属性,读属性和写属性。
第一个线程加读锁,第二个线程也加读锁------》成功
第一个线程加读锁,以后的多个线程既有加写锁的,又有加读锁的------》第一次加读锁成功,以后的读写锁会阻塞随后的加读锁,优先满足加写锁
第一个线程加写锁,第二个线程也加读锁------》加写锁成功,加读锁会阻塞
第一个线程加写锁,第二个线程也加写锁------》第一次加写锁成功,第二次加写锁会阻塞
读写锁的加锁和解锁:
//读写锁的特性:只有都加读锁才不会阻塞;读写、写读、写写,只有第一次加锁能成功,第二次加锁会阻塞。 #include <string.h> #include <stdio.h> #include <pthread.h> #include <unistd.h> pthread_rwlock_t rwlock; void *f1(void *arg) { pthread_rwlock_rdlock(&rwlock); printf("t1 runing....r..\n"); sleep(2); return (void *)0; } void *f2(void *arg) { pthread_rwlock_rdlock(&rwlock); printf("t2 runing...r...\n"); sleep(2); return (void *)0; } int main(int argc, char *argv[]) { /* if(argc < 2){ printf("parame too few \n"); } */ pthread_t t1,t2; pthread_rwlock_init(&rwlock, NULL); if(pthread_create(&t1, NULL, f1, (void *)0) < 0){ printf("pthread_create failed\n"); } if(pthread_create(&t2, NULL, f2, (void *)0) < 0){ printf("pthread_create failed\n"); } pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock); pthread_rwlock_destroy(&rwlock); return 0; }