ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Linux 线程同步

Linux 线程同步 使多个线程线性执行防止共享数据错乱互斥锁保证锁不会被半途释放掉全局变量临界区越小越好pthread_mutex_t mutex;死锁情况如何解决读写锁#include stdio.h #include stdlib.h #include unistd.h #include string.h #include pthread.h //全局变量 int num 0; //定义读写锁 pthread_rwlock_t rwlock; void* writefun(void* arg) { while (1) { //加写锁 pthread_rwlock_wrlock(rwlock); printf(num%d,id%ld\n, num, pthread_self()); num; //解锁 pthread_rwlock_unlock(rwlock); // 添加sleep目的是要看到多个线程交替工作 usleep(rand() % 100); } return NULL; } void* readfun(void* arg) { while (1) { pthread_rwlock_rdlock(rwlock); printf(--全局变量number %d, tid %ld\n, num, pthread_self()); pthread_rwlock_unlock(rwlock); usleep(rand() % 100); } return NULL; } int main() { //初始化读写锁 pthread_rwlock_init(rwlock, NULL); //创建子线程 pthread_t wpid[3]; pthread_t rpid[5]; for (int i 0; i 3; i) { pthread_create(wpid[i], NULL, writefun, NULL); } for (int i 0; i 5; i) { pthread_create(rpid[i], NULL,readfun, NULL); } //释放资源 for (int i 0; i 3; i) { pthread_join(wpid[i], NULL); } for (int i 0; i 5; i) { pthread_join(rpid[i], NULL); } // 销毁读写锁 pthread_rwlock_destroy(rwlock); return 0; }条件变量生产消费者模型仓库满了生产阻塞。仓库空了消费者阻塞pthread_cond_wait(cond, mutex);1.阻塞线程前把互斥锁打卡2.阻塞线程3.线程阻塞解除自动给线程加上互斥锁#include stdio.h #include stdlib.h #include unistd.h #include string.h #include pthread.h // 链表的节点 struct Node { int number; struct Node* next; }; // 定义条件变量, 控制消费者线程 pthread_cond_t cond; // 互斥锁变量 pthread_mutex_t mutex; // 指向头结点的指针 struct Node * head NULL; // 生产者的回调函数 void* producer(void* arg) { // 一直生产 while(1) { pthread_mutex_lock(mutex); // 创建一个链表的新节点 struct Node* pnew (struct Node*)malloc(sizeof(struct Node)); // 节点初始化 pnew-number rand() % 1000; // 节点的连接, 添加到链表的头部, 新节点就新的头结点 pnew-next head; // head指针前移 head pnew; printf(producer, number %d, tid %ld\n, pnew-number, pthread_self()); pthread_mutex_unlock(mutex); // 生产了任务, 通知消费者消费 pthread_cond_broadcast(cond); // 生产慢一点 sleep(rand() % 3); } return NULL; } // 消费者的回调函数 void* consumer(void* arg) { while(1) { pthread_mutex_lock(mutex); // 一直消费, 删除链表中的一个节点 // if(head NULL) // 这样写有bug while(head NULL) { // 任务队列, 也就是链表中已经没有节点可以消费了 // 消费者线程需要阻塞 // 线程加互斥锁成功, 但是线程阻塞在这行代码上, 锁还没解开 // 其他线程在访问这把锁的时候也会阻塞, 生产者也会阻塞 死锁 // 这函数会自动将线程拥有的锁解开 pthread_cond_wait(cond, mutex); // 当消费者线程解除阻塞之后, 会自动将这把锁锁上 // 这时候当前这个线程又重新拥有了这把互斥锁 } // 取出链表的头结点, 将其删除 struct Node* pnode head; printf(--consumer: number: %d, tid %ld\n, pnode-number, pthread_self()); head pnode-next; free(pnode); pthread_mutex_unlock(mutex); sleep(rand() % 3); } return NULL; } int main() { // 初始化条件变量 pthread_cond_init(cond, NULL); pthread_mutex_init(mutex, NULL); // 创建5个生产者, 5个消费者 pthread_t ptid[5]; pthread_t ctid[5]; for(int i0; i5; i) { pthread_create(ptid[i], NULL, producer, NULL); } for(int i0; i5; i) { pthread_create(ctid[i], NULL, consumer, NULL); } // 释放资源 for(int i0; i5; i) { // 阻塞等待子线程退出 pthread_join(ptid[i], NULL); } for(int i0; i5; i) { pthread_join(ctid[i], NULL); } // 销毁条件变量 pthread_cond_destroy(cond); pthread_mutex_destroy(mutex); return 0; }pthread_cond_signal / broadcast只唤醒卡在pthread_cond_wait上的线程不会唤醒卡在pthread_mutex_lock的线程pthread_mutex_lock的线程什么时候醒只有别人执行pthread_mutex_unlock的那一刻才会去竞争锁。消费者部分pthread_cond_wait先释放你已经拿到的mutex解锁有可能生产者抢到线程阻塞等待条件变量cond被唤醒被唤醒之后自动重新去抢这把 mutex抢到锁函数才返回然后执行后面节点删除代码信号量#include stdio.h #include stdlib.h #include unistd.h #include string.h #include semaphore.h #include pthread.h // 链表的节点 struct Node { int number; struct Node* next; }; // 生产者线程信号量 sem_t psem; // 消费者线程信号量 sem_t csem; // 互斥锁变量 pthread_mutex_t mutex; // 指向头结点的指针 struct Node * head NULL; // 生产者的回调函数 void* producer(void* arg) { // 一直生产 while(1) { // 生产者拿一个信号灯 sem_wait(psem); // 加锁, 这句代码放到 sem_wait()上边, 有可能会造成死锁 pthread_mutex_lock(mutex); // 创建一个链表的新节点 struct Node* pnew (struct Node*)malloc(sizeof(struct Node)); // 节点初始化 pnew-number rand() % 1000; // 节点的连接, 添加到链表的头部, 新节点就新的头结点 pnew-next head; // head指针前移 head pnew; printf(producer, number %d, tid %ld\n, pnew-number, pthread_self()); pthread_mutex_unlock(mutex); // 通知消费者消费 sem_post(csem); // 生产慢一点 sleep(rand() % 3); } return NULL; } // 消费者的回调函数 void* consumer(void* arg) { while(1) { sem_wait(csem); pthread_mutex_lock(mutex); struct Node* pnode head; printf(--consumer: number: %d, tid %ld\n, pnode-number, pthread_self()); head pnode-next; // 取出链表的头结点, 将其删除 free(pnode); pthread_mutex_unlock(mutex); // 通知生产者生成, 给生产者加信号灯 sem_post(psem); sleep(rand() % 3); } return NULL; } int main() { // 初始化信号量 sem_init(psem, 0, 5); // 生成者线程一共有5个信号灯 sem_init(csem, 0, 0); // 消费者线程一共有0个信号灯 // 初始化互斥锁 pthread_mutex_init(mutex, NULL); // 创建5个生产者, 5个消费者 pthread_t ptid[5]; pthread_t ctid[5]; for(int i0; i5; i) { pthread_create(ptid[i], NULL, producer, NULL); } for(int i0; i5; i) { pthread_create(ctid[i], NULL, consumer, NULL); } // 释放资源 for(int i0; i5; i) { pthread_join(ptid[i], NULL); } for(int i0; i5; i) { pthread_join(ctid[i], NULL); } sem_destroy(psem); sem_destroy(csem); pthread_mutex_destroy(mutex); return 0; }因为产者线程有多个资源可以多线程因此要线程同步加删互斥锁加锁要在资源变量减一之后对于消费者一开始资源量为0运行到这里semltimedwait阻塞但是此时已经加锁了哪怕生产者想要生产都被阻塞了semwait会阻塞无资源
返回列表