Linux-线程同步

线程同步

Posted by MetaNetworks on September 1, 2019
本页面总访问量

代码记录:

5个人(使用线程模拟)用5支筷子吃饭的问题。

需要解决的问题:

  • 等所有人吃完就终止
  • 防止死锁

使用到的知识:

  • pthread
    • pthread_mutex_trylock
      • 非阻塞尝试加锁,成功返回0
    • pthread_mutex_unlock
      • 解除锁
    • pthread_create(&mThread[i],NULL,thread_do,&index_arr[i])
      • 创建进程,参数分别为线程地址,attr,启动函数,启动参数(void *)
    • pthread_join(mThread[i],NULL);
  • unistd.h
    • POSIX API中的sleep函数

PS:引入AND信号量,避免产生环路等待。(申请多个,只要没有全部申请到就丢弃,重新申请)

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
#include <iostream>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/malloc.h>

#define PEO_NUM 5
#define EAT_SEC 3
#define WAIT_SEC 1
#define OK 0
#define ERR -1

pthread_mutex_t chopstick[5];

pthread_mutex_t * getStickIndex(int index){
    return &chopstick[index];
}

void dropStick(int stick_num){
    if(pthread_mutex_unlock(&chopstick[stick_num])){
        printf("错误:筷子%d放不下了!",stick_num);
    }
}


int takeStick(int stick_n1,int stick_n2){
    //printf("尝试去拿筷子%d\n",stick_num);

    UNLOCK_N1:
    while(pthread_mutex_trylock(&chopstick[stick_n1])){
        sleep(WAIT_SEC);
    }

    UNLOCK_N2:
    while(pthread_mutex_trylock(&chopstick[stick_n2])){
        //把前面获得的筷子扔了
        sleep(WAIT_SEC);
        printf("拿不到%d号筷子,于是把%d号筷子扔了了事\n",stick_n2,stick_n1);
        dropStick(stick_n1);
        goto UNLOCK_N1;
    }

    return OK;
}

void eat(){
    // sleep for sec
    sleep(EAT_SEC);
}

void * thread_do(void * arg){
    int _THREAD_NUM=*(int*)arg;
    //printf("线程%d报道~\n",_THREAD_NUM);

    takeStick(_THREAD_NUM,(_THREAD_NUM+1)%PEO_NUM);
    //拿到了_THREAD_NUM筷子
    printf("线程%d正在恰饭\n",_THREAD_NUM);
    eat();
    dropStick(_THREAD_NUM);
    dropStick((_THREAD_NUM+1)%5);
    return NULL;
}

int main(){

    int index_arr[5]={0,1,2,3,4};
    //初始化资源
    for (int i = 0; i < 5; i++)
    {
        pthread_mutex_init(&chopstick[i],NULL);
    }
    //构造线程
    pthread_t mThread[5];
    for(int i=0;i<5;i++){
        
        if (pthread_create(&mThread[i],NULL,thread_do,&index_arr[i]) == 0)
        {
            //printf("线程%d 创建成功!\n",i);
        }
    }

    for (int i = 0; i < 5; i++)
    {
        //printf("主线程正在等待%d号子线程\n",i);
        pthread_join(mThread[i],NULL);
        //printf("线程%d已退出!\n",i);
    }
    
    return 0;
}