多线程,同步,互斥(生产者/消费者)
数据污读:bool 的 true 和 bool 的 false , 当1线程执行true时读文件, 为false时2线程读文件,但是由于线程的cpu分时复用,可能还会执行 true 操作 , 导致读入数据异常 . 线程之间数据共享:
污读:
A--(读)-->data
B--(写)-->data
污写: A--(true) bool flag B--(false) bool flag
解决方法:原子性 : 就是在执行读操作的时候需要把读操作执行完毕 , 执行写操作的时候需要把写操作执行完毕 .
互斥:指两个或两个以上的任务,每次只能有一个任务访问某资源。
其他任务必须等待。
reader:
lock l;
read
unlock l;
author:
lock l;
write;
unlock l;
上锁实现互斥的操作 :
#include<stdio.h>
#include<pthread.h>
//两个线程:一个读,一个写
int lock_var;
//定义互斥量
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
//互斥:读者读时,写者不能写,反之一样.
//同步:先写,再读(按照顺序)
void* reader(void* arg)//读者
{
char* pb=(char*)arg;
while(1)
{
//上锁
pthread_mutex_lock(&mutex);
//读取
printf("读取的内容为:%s\n",pb);
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void* author(void* arg)//写者
{
char* pb=(char*)arg;
while(1)
{
//上锁
pthread_mutex_lock(&mutex);
//写入
printf("请输入内容:\n");
scanf("%s",pb);
printf("写入完成\n");
//解锁
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
//读写者问题:
int main()
{
//共同缓冲区
char buf[100]="";
//创建两个线程
pthread_t rtid,wtid;
pthread_create(&rtid,NULL,reader,buf);
pthread_create(&wtid,NULL,author,buf);
//等待子线程结束
pthread_join(rtid,NULL);
pthread_join(wtid,NULL);
//销毁锁
pthread_mutex_destroy(&mutex);
return 0;
}
通过信号量来实现互斥 :
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t m1,m2;
//两个线程:一个读,一个写
//互斥:读者读时,写者不能写,反之一样.
//同步:先写,再读(按照顺序)
void* reader(void* arg)//读者
{
while(1)
{
sem_wait(&m1);
printf("我是---A线程\n");
sleep(1);
sem_post(&m2);
}
}
void* author(void* arg)//写者
{
while(1)
{
sem_wait(&m2);
printf("我是---B线程\n");
sleep(1);
sem_post(&m1);
}
}
//读写者问题:
int main()
{
//创建两个线程
sem_init(&m1,0,0);//m1读者
sem_init(&m2,0,1);//m2作者
//共同缓冲区
char buf[100]="";
pthread_t rtid,wtid;
pthread_create(&rtid,NULL,reader,buf);
pthread_create(&wtid,NULL,author,buf);
//等待子线程结束
pthread_join(rtid,NULL);
pthread_join(wtid,NULL);
return 0;
}
通过信号量实现分别打印 A , B , C 的字符 .
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
//定义三个信号量
sem_t sa,sb,sc;
//线程函数
void* threadfun(void* arg)
{
char ch=(int)arg;
while(1)
{
if(ch=='A')
sem_wait(&sa);
else if(ch=='B')
sem_wait(&sb);
else
sem_wait(&sc);
printf("%c\n",ch);
sleep(1);
//v操作
if(ch=='A')
sem_post(&sb);
else if(ch=='B')
sem_post(&sc);
else
sem_post(&sa);
}
return NULL;
}
int main()
{
sem_init(&sa,0,0);
sem_init(&sb,0,0);
sem_init(&sc,0,1);
//创建线程
pthread_t tid[3];
char ch='A';
for(;ch<='C';ch++)
{
//创建
pthread_create(&tid[ch-'A'],NULL,threadfun,(void*)ch);
}
//等待线程结束
for(ch=0;ch<=2;ch++)
pthread_join(tid[ch],NULL);
sem_destroy(&sa);
sem_destroy(&sb);
sem_destroy(&sc);
return 0;
}
同步:指定为了完成某种任务而建立两个或两个以上的进程/线程,这些进程/线程在合作中需要“协调工作次序”进行有行的访问而出现等待所产生的制约关系。
产生者/消费者 (模型)
描述:一组生产者和一组消费者共享一块初始为空的空间;
大小确定的缓冲区;
生产者:当空间为满时,必须等待。否则可以生产车。
消费者:只有缓冲区不为空是才能消费,否则必须等待。
缓冲区一次只能访问一个进程(临界资源)
问题:生产者与消费者对缓冲区是互斥关系(关系)。
生产者与消费又存在协同关系(必须先生产后消费)
解决:1、互斥:互斥锁
2、信号量:
对缓冲区设置为空闲区数信号量和满区的数信号量。
伪代码:
semaphore full=0 //满区的数量(当前实际量)
semaphore empty=100 //可存储量
lock mutex; //锁
//生产者:
prodecer(){
while(1){
p(empty)//发现有仓库不为满,
lock(mutex);
add_source++;//生产并存放
v(full)
unlock(mutex);
}
}
//消费者:
consumer(){
while(1){
p(full) //发现仓库车的数量是否为空
lock(mutex)
add_source--;//消费
v(empty);
unlock(mutex)
}
}
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<stdlib.h>
#include<unistd.h>
//定义信号量
sem_t empty,full;//empty仓库空闲区的数量 full为商品
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
//仓库:
struct store
{
int buf[10];
int ilen;
};
//定义结构体:
struct store s={0};
//生产者
void* productor(void* arg)
{
while(1)
{
pthread_mutex_lock(&mutex);
sem_wait(&empty);//p操作 有空闲区
//生产
sleep(rand()%2);//随机值
printf("生产者生产的汽车标号为:%d",s.buf[s.ilen++]=rand());
printf("-->当前一共有%d辆车\n",s.ilen);
//货物数量+1
sem_post(&full);//货物数量+1
pthread_mutex_unlock(&mutex);
}
}
//消费者
void* consumer(void* arg)
{
while(1)
{
//P操作---买车(消耗货物)
pthread_mutex_lock(&mutex);
sem_wait(&full);
//消费
sleep(rand()%2);
printf("购买的车的ID:%d",s.buf[--s.ilen]);
printf("-->当前一共有%d辆车\n",s.ilen);
sem_post(&empty);
pthread_mutex_unlock(&mutex);
}
}
int main()
{
//初始化
sem_init(&empty,0,10);//空区数量
sem_init(&full,0,0); //商品数量
//创建两个线程:
pthread_t ctid,ptid;//consumer productor
pthread_create(&ptid,NULL,productor,NULL);//生产者
pthread_create(&ctid,NULL,consumer,NULL); //消费者
//等待
pthread_join(ctid,NULL);
pthread_join(ptid,NULL);
//销毁
sem_destroy(&empty);
sem_destroy(&full);
//销毁锁
pthread_mutex_destroy(&mutex);
}
上一篇: 软件工程师相关日语