Linux-(信号量)隧道过车

一个隧道左右两侧可以通车...

Posted by MetaNetworks on October 20, 2019
本页面总访问量

隧道过车

一个隧道左右两侧可以通车,一侧车辆可以连续通过,如果右侧通车则左侧的车停止等待。右侧的最后一辆车通过隧道后给左侧的第一个车发送信号让它开始通过隧道。反之同理。(读者写者问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * @Author: MetaNetworks
 * @Date: 2019-10-20 18:03:23
 * @LastEditors: MetaNetworks
 * @LastEditTime: 2019-10-20 19:40:24
 * @Description: MetaNetworks' Code
 */
//一个隧道左右两侧可以通车,一侧车辆可以连续通过,
//如果右侧通车则左侧的车停止等待。
//右侧的最后一辆车通过隧道后给左侧的第一个车发送信号让它开始通过隧道。
//反之同理。(读者写者问题)
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
// MultiProcess
#include <pthread.h>
// Semaphore
#include <semaphore.h>
// Register Signal
#include <csignal>
//参数定义
#define LEFTCAR_NUM 10 // 总共预设的隧道左边车的数量
#define RIGHTCAR_NUM 10 // 总共预设的隧道右边车的数量
// 信号量1:互斥信号量,左边有没有车
sem_t* sem_left_car;
// 信号量2:互斥信号量,右边有没有车
sem_t* sem_right_car;
// 数据
int left_wait_car_num = 0;
int right_wait_car_num = 0;
int lefted = 0;
int righted = 0;
// 行为函数
void * leftCar(void *);
void * rightCar(void *);
void sig_handler(int sig);
// 主函数
int main(int argc, char const *argv[]){
    // 注册 Register,让其相应 ctrl+c 取消操作
    signal(SIGINT,sig_handler);
    // 20 customers
    pthread_t leftCars[LEFTCAR_NUM];
    // 1 window
    pthread_t rightCars[RIGHTCAR_NUM];
    // initail 
    sem_left_car = sem_open("/leftCars",O_CREAT,0644,1);
    sem_right_car = sem_open("/rightCars",O_CREAT,0644,1);
    // leftCar
    for (int i = 0; i < LEFTCAR_NUM; i++)
    {
        pthread_create(&leftCars[i],NULL,&leftCar,NULL);
    }
    // rightCar
    for (int i = 0; i < RIGHTCAR_NUM; i++)
    {
        pthread_create(&rightCars[i],NULL,&rightCar,NULL);
    }

    // leftCar join
    for (int i = 0; i < RIGHTCAR_NUM; i++)
    {
        pthread_join(leftCars[i],NULL);
    }
    // rightCar join
    for (int i = 0; i < RIGHTCAR_NUM; i++)
    {
        pthread_join(rightCars[i],NULL);
    }
    sig_handler(SIGINT);
    return 0;
}

// 按下Ctrl+C后需要销毁
void sig_handler(int sig){
    if (sig == SIGINT)
    {
        // destory semephrone
        printf("\n销毁信号量\n");
        sem_unlink("/leftCars");
        sem_unlink("/rightCars");
        exit(0);
    }
}

// show message in terminal
void * showMessage(char* words){
    printf("%s\n",words);
    return NULL;
}

void * leftCar(void *){
    //showMessage("我是一名左边的司机");
    sem_wait(sem_left_car);
    if (left_wait_car_num == 0)
    {
        // 是第一个往右边走的,要看右边有没有车
        sem_wait(sem_right_car);
    }
    left_wait_car_num += 1;
    sem_post(sem_left_car);
    lefted += 1;
    printf("左边一司机:已通行 %d 辆!\n",lefted);
    // 要修改left_wait_car_num了
    sem_wait(sem_left_car);
    left_wait_car_num -= 1;
    if (left_wait_car_num == 0)
    {
        // 左边没车了,通知右边的
        sem_post(sem_right_car);
        //printf("左边一司机:左边没车了,右边司机来吧!\n");
    }
    sem_post(sem_left_car);
    return NULL;
}

void * rightCar(void *){
    //showMessage("我是一名右边的司机");
    sem_wait(sem_right_car);
    if (right_wait_car_num == 0)
    {
        // 是第一个往左边走的,要看左边有没有车
        sem_wait(sem_left_car);
    }
    right_wait_car_num += 1;
    sem_post(sem_right_car);
    righted += 1;
    printf("右边一司机:已通行 %d 辆!\n",righted);
    // 要修改right_wait_car_num了
    sem_wait(sem_right_car);
    right_wait_car_num -= 1;
    if (right_wait_car_num == 0)
    {
        // 右边没车了,通知左边的
        sem_post(sem_left_car);
        //printf("右边一司机:右边没车了,左边司机来吧!\n");
    }
    sem_post(sem_right_car);
    return NULL;
}

运行结果

编译使用g++,参数为”-pthread”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
MetaNetworks@jintaodeMacBook-Air  ~/CppProject/Linux  ./psSynchronize2
左边一司机:已通行 2 辆!
左边一司机:已通行 7 辆!
左边一司机:已通行 9 辆!
左边一司机:已通行 10 辆!
左边一司机:已通行 1 辆!
左边一司机:已通行 3 辆!
左边一司机:已通行 4 辆!
左边一司机:已通行 5 辆!
左边一司机:已通行 6 辆!
左边一司机:已通行 8 辆!
右边一司机:已通行 1 辆!
右边一司机:已通行 2 辆!
右边一司机:已通行 5 辆!
右边一司机:已通行 4 辆!
右边一司机:已通行 7 辆!
右边一司机:已通行 6 辆!
右边一司机:已通行 3 辆!
右边一司机:已通行 8 辆!
右边一司机:已通行 9 辆!
右边一司机:已通行 10 辆!