linux知识(二)互斥量、信号量和生产者消费者模型
- 一、互斥量
- 产生原因
- 二、信号量
- 生产者消费者模型
一、互斥量
产生原因
使用多线程常常会碰到数据混乱的问题,那么使用互斥量,相当于“加锁”的操作,将有助于解决数据混乱的问题
每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁
资源还是共享的,线程间也还是竞争的,
但通过“锁”就将资源的访问变成互斥操作,而后与时间有关的错误也不会再产生了。
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>pthread_mutex_t mutex; //定义锁
void* tfn(void* arg)
{srand(time(NULL));while (1) {pthread_mutex_lock(&mutex);printf("hello ");sleep(rand() % 3); /*模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误*/printf("world\n");pthread_mutex_lock(&mutex);pthread_mutex_unlock(&mutex);sleep(rand() % 3);}return NULL;
}int main(void)
{int flg = 5;pthread_t tid;srand(time(NULL));pthread_mutex_init(&mutex,NULL); //mutex==1,初始化锁pthread_create(&tid,NULL,tfn,NULL);while (1) {pthread_mutex_lock(&mutex);printf("HELLO ");sleep(rand() % 3);printf("WORLD\n");pthread_mutex_unlock(&mutex);sleep(rand() % 3);}pthread_cancel(tid);pthread_join(tid, NULL);pthread_mutex_destroy(&mutex);return 0;
}
二、信号量
互斥量的操作是1对1的,一个线程加锁与解锁完成后,下一个线程通过竞争在拿到锁进行操作,对于多线程并发来说,无形间效率就变低了。多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。线程从并行执行,变成了串行执行。与直接使用单进程无异。信号量能有效的解决这一问题。
生产者消费者模型
说到信号量,就必须提到生产者消费者模型
我们来假设一下这样一个情景,图中有生产者,消费者以及有5个盘子。生产者只有生产了,消费者才能拿到东西。我们定义5个线程来当作生产者持续生产,它们需要拿到盘子来生产,它们不在像用拿“锁”的方式一个一个来生产,这样无形之中就提高了效率,提高了并发型。消费等生产者生产完,通过竞争来抢这些消费品。
#include <cstdio>
#include <pthread.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <string.h>using namespace std;
int g_count=0;
pthread_mutex_t prod_mutex;
pthread_mutex_t cur_mutex;
sem_t g_sem_prod;//生产者信号量
sem_t g_sem_cur; //消费者的信号量void * add(void *arg)
{//生产者cout << " thread .. wait .. id = " << pthread_self() << endl;//开启保护线程sem_wait(&g_sem_prod);pthread_mutex_lock(&prod_mutex);g_count++;printf("make cake ... g_count = %d\n",g_count);//解除保护pthread_mutex_unlock(&prod_mutex);sem_post(&g_sem_cur);sleep(rand() % 3);}void* sub(void* arg)
{//消费者cout << "wait cake thread .. wait .. id = " << pthread_self() << endl;sem_wait(&g_sem_cur);//开启保护线程pthread_mutex_lock(&cur_mutex);g_count--;printf("eat.......g_count = %d\n", g_count);//解除保护pthread_mutex_unlock(&cur_mutex);sem_post(&g_sem_prod);sleep(rand() % 3);}int main()
{int i = 0;pthread_t tid;int ret;pthread_mutex_init(&prod_mutex,NULL);pthread_mutex_init(&cur_mutex, NULL);sem_init(&g_sem_prod,0,5);sem_init(&g_sem_cur,0, 0);//线程 加一操作for (i = 0; i < 5; i++){ret = pthread_create(&tid, NULL, add, NULL);if (ret != 0){cout << strerror(ret) << endl;return 0;}}//消费者for (i = 0; i < 5; i++){ret=pthread_create(&tid, NULL, sub, NULL);if (ret != 0){cout << strerror(ret) << endl;return 0;}}while (1){}return 0;
}