一、互斥量
产生原因
使用多线程常常会碰到数据混乱的问题,那么使用互斥量,相当于“加锁”的操作,将有助于解决数据混乱的问题
每个线程在对资源操作前都尝试先加锁,成功加锁才能操作,操作结束解锁
资源还是共享的,线程间也还是竞争的,
但通过“锁”就将资源的访问变成互斥操作,而后与时间有关的错误也不会再产生了。
#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;
}