进程同步
Posted 丁帅帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了进程同步相关的知识,希望对你有一定的参考价值。
1、实现两或多个进程之间互斥访问临界资源(先写出PV操作的伪算法,然后进行算法实现)
PV操作
semaphore mutex=1; //临界区互斥信号量
while(1){
sleep(1);
P(mutex);
printf("father in\\n");
sleep(1);
printf("father out\\n");
V(mutex);
}
while(1){
sleep(1);
P(mutex);
printf("child in\\n");
sleep(1);
printf("child out\\n");
V(mutex);
}
代码实现
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<linux/sem.h>
#include <sys/wait.h>
int mutex;
int P(int sem_id)
{
struct sembuf p;
p.sem_num = 0;
p.sem_op = -1;
p.sem_flg = SEM_UNDO;
if (semop(sem_id,&p,1) == -1)
{
fprintf(stderr, "P failed\\n");
return 0;
}
return 1;
}
int V(int sem_id)
{
struct sembuf v;
v.sem_num = 0;
v.sem_op = 1;
v.sem_flg = SEM_UNDO;
if (semop(sem_id,&v,1) == -1)
{
fprintf(stderr, "V failed\\n");
return 0;
}
return 1;
}
int main()
{
int child, i, j;
// 定义信号量,初值为1
mutex = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if (semctl(mutex, 0, SETVAL, 1) == -1)
{
perror("semctl setval error");
}
child = fork();
while (1)
{
if (child == -1)
{
printf("error");
}
// 父进程
else if (child > 0)
{
i = 1;
while (i <= 3)
{
sleep(1);
P(mutex);
printf("father in\\n");
sleep(1);
printf("father out\\n");
V(mutex);
i++;
}
wait(NULL);
semctl(mutex, IPC_RMID, 0);
exit(0);
}
// 子进程
else if (child == 0)
{
j = 1;
while (j <= 3)
{
sleep(1);
P(mutex);
printf("child in\\n");
sleep(1);
printf("child out\\n");
V(mutex);
j++;
}
}
}
return 0;
}
截图
2、实现不死锁的哲学家进餐问题(先写出PV操作的伪算法,然后进行算法实现)
PV操作
semaphore chopstick[5]={1,1,1,1,1};
semaphore mutex = 4; //互斥地取筷子,至多四个人同时拿左边的筷子,保证至少有一个人可以进餐,最终释放筷子使更多的人进餐
Pi (){ //i号哲学家的进程
while(1){
思考…
P(mutex);
P(chopstick[i]); //拿左
P(chopstick[(i+1)%5]); //拿右
吃饭…
V(chopstick[i]); //放左
V(chopstick[(i+1)%5]); //放右
V(mutex);
}
}
代码实现
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<signal.h>
#include<errno.h>
#include<fcntl.h>
int mutex = 4;//互斥地取筷子
int chopstick[5];
int P(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
// 进行p操作
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "P failed\\n");
return 0;
}
return 1;
}
int V(int sem_id) // 释放资源
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
// 进行v操作
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "V failed\\n");
return 0;
}
return 1;
}
int main()
{
mutex = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
semctl(mutex, 0, SETVAL, 4); // 至多只允许四个哲学家同时进餐,至少有一个可以拿到筷子
int i = 0;
pid_t pid;
pid_t pids[3];
char ch;
for (i = 0; i < 5; ++i)
{
chopstick[i] = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
semctl(chopstick[i], 0, SETVAL, 1);
}
for (i = 0; i < 5; ++i)
{
pid = fork();
if (pid == 0)
{
while (1)
{
printf(" %d 哲学家在思考\\n",i);
sleep(1);
P(mutex);
printf("%d 哲学家饿了,准备开始吃饭\\n",i);
P(chopstick[i]);
printf("%d 哲学家拿左筷子\\n", i);
P(chopstick[(i + 1) % 5]);
printf("%d哲学家拿右筷子\\n", i);
printf("%d 哲学家有两只筷子后,开始进餐!\\n", i);
V(chopstick[(i + 1) % 5]);
printf(" %d 吃完饭了,释放右筷子\\n", i);
V(chopstick[i]);
printf("%d 哲学家吃完饭了,释放左筷子\\n", i);
V(mutex);
}
}
}
do{
ch = getchar();
if (ch == \'q\')
{
for (i = 0; i < 3; ++i)
{
kill(pids[i],SIGTERM);
}
}
}while(ch != \'q\');
return 0;
}
截图
3、苹果-橘子问题,一个盘子可以放3个水果,爸爸放,儿子和女儿吃,假设儿子和女儿有永远吃不饱。(先写出PV操作的伪算法,然后进行算法实现)
PV操作
semaphore empty =3; // 盘子中最多容纳3个水果
semaphore full = 0; // 盘子现在不满,且0个水果
semaphore orange=0;//盘子中橘子的数量
semaphore apple=0;//盘子中苹果的数量
dad(){
while(1){
if (rand() % 2 == 1)//随机放
{
准备一个苹果;
p(empty);//申请一个盘子
V(apple);//唤醒女儿吃苹果
}
else
{
准备一个橘子;
P(empty);//申请一个盘子
向盘子放橘子;
V(orange);//唤醒儿子吃苹果
}
}
}
daughter(){
while(1){
P(orange);//申请橘子,若orange=0,则等待放入水果
从盘子拿橘子;
V(empty);///释放一个盘子
吃橘子;
}
}
son(){
while(){
P(apple);//申请苹果,若apple=0,则等待父亲放入水果
从盘子中拿苹果;
V(empty);//释放一个盘子
}
}
代码
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<signal.h>
#include<errno.h>
#include<fcntl.h>
int P(int sem_id)
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1;
sem_b.sem_flg = SEM_UNDO;
// 进行p操作
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "P failed\\n");
return 0;
}
return 1;
}
int V(int sem_id) // 释放资源
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1;
sem_b.sem_flg = SEM_UNDO;
// 进行v操作
if (semop(sem_id, &sem_b, 1) == -1)
{
fprintf(stderr, "V failed\\n");
return 0;
}
return 1;
}
int main()
{
int i = 0;
pid_t pid;
pid_t pids[3];
char ch;
int empty; // 盘子中是否为空
int full; // 盘子中是否为满
int apple; // 苹果有几个
int orange; // 橘子有几个
empty = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if (semctl(empty, 0, SETVAL, 3) == -1) // 盘子中最多容纳3个水果
{
perror("semctl setval error");
}
full = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if (semctl(full, 0, SETVAL, 0) == -1) // 盘子现在不满,且0个水果
{
perror("semctl setval error");
}
apple = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if (semctl(apple, 0, SETVAL, 0) == -1)
{
perror("semctl setval error");
}
orange = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
if (semctl(orange, 0, SETVAL, 0) == -1)
{
perror("semctl setval error");
}
for (i = 0; i < 3; ++i)
{
pid = fork();
if (pid == 0)
{
while (1)
{
if (pid == 0 && i == 0)
{
P(empty);
if (rand() % 2 == 1)//随机放
{
printf("爸爸向盘子中放苹果\\n");
V(apple);
V(full);
}
else
{
printf("爸爸向盘子中放橘子\\n");
V(orange);
V(full);
}
sleep(2);
}
else if (pid == 0 && i == 1)
{
P(full);
P(apple);
printf("儿子从盘子中取走苹果\\n");
V(empty);
sleep(2);
}
else if (pid == 0 && i == 2)
{
P(full);
P(orange);
printf("女儿从盘子中取走橘子\\n", empty);
V(empty);
sleep(2);
}
}
}
}
do{
ch = getchar();
if (ch == \'q\')
{
for (i = 0; i < 3; ++i)
{
kill(pids[i],SIGTERM);
}
}
}while(ch != \'q\');
return 0;
}
截图
有的要别人来设定目标,有的给别人设定目标;
有的需要感情支持生活,有的需要意志支持生活。
以上是关于进程同步的主要内容,如果未能解决你的问题,请参考以下文章
在 Python 多处理进程中运行较慢的 OpenCV 代码片段
[工作积累] UE4 并行渲染的同步 - Sync between FParallelCommandListSet & FRHICommandListImmediate calls(代码片段