• 第三章 Linux多线程开发 线程取消 属性 同步 互斥锁 死锁 读写锁 生产者消费者 信号量


    在这里插入图片描述

    线程取消:

    /*
        #include 
        int pthread_cancel(pthread_t thread);
            - 功能:取消线程(让线程终止)
                取消某个线程,可以终止某个线程的运行,
                但是并不是立马终止,而是当子线程执行到一个取消点,线程才会终止。
                取消点:系统规定好的一些系统调用,我们可以粗略的理解为从用户区到内核区的切换,这个位置称之为取消点。
    */
    
    #include 
    #include 
    #include 
    #include 
    
    void * callback(void * arg) {
        printf("chid thread id : %ld\n", pthread_self());
        for(int i = 0; i < 5; i++) {
            printf("child : %d\n", i);
        }
        return NULL;
    }
    
    int main() {
        
        // 创建一个子线程
        pthread_t tid;
    
        int ret = pthread_create(&tid, NULL, callback, NULL);
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error1 : %s\n", errstr);
        }
    
        // 取消线程 不是立刻取消的  
        pthread_cancel(tid);
    
        for(int i = 0; i < 5; i++) {
            printf("%d\n", i);
        }
    
        // 输出主线程和子线程的id
        printf("tid : %ld, main thread id : %ld\n", tid, pthread_self());
    
        
        pthread_exit(NULL);
    
        return 0;
    }
    
    • 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

    线程属性

    /*
        int pthread_attr_init(pthread_attr_t *attr);
            - 初始化线程属性变量
    
        int pthread_attr_destroy(pthread_attr_t *attr);
            - 释放线程属性的资源
    
        int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
            - 获取线程分离的状态属性
    
        int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
            - 设置线程分离的状态属性
    */     
    
    #include 
    #include 
    #include 
    #include 
    
    void * callback(void * arg) {
        printf("chid thread id : %ld\n", pthread_self());
        return NULL;
    }
    
    int main() {
    
        // 创建一个线程属性变量
        pthread_attr_t attr;
        // 初始化属性变量
        pthread_attr_init(&attr);
    
        // 设置属性
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    
        // 创建一个子线程
        pthread_t tid;
    
        int ret = pthread_create(&tid, &attr, callback, NULL);
        if(ret != 0) {
            char * errstr = strerror(ret);
            printf("error1 : %s\n", errstr);
        }
    
        // 获取线程的栈的大小
        size_t size;
        pthread_attr_getstacksize(&attr, &size);
        printf("thread stack size : %ld\n", size);
    
        // 输出主线程和子线程的id
        printf("tid : %ld, main thread id : %ld\n", tid, pthread_self());
    
        // 释放线程属性资源
        pthread_attr_destroy(&attr);
    
        pthread_exit(NULL);
    
        return 0;
    }
    
    • 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

    线程同步

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    多线程实现卖票:

    selltickets.c(没有加锁的情况) 线程同步

    /*
        使用多线程实现买票的案例。
        有3个窗口,一共是100张票。
    */
    
    #include 
    #include 
    #include 
    
    // 全局变量,所有的线程都共享这一份资源。
    int tickets = 100;
    
    void * sellticket(void * arg) {
        // 卖票
        while(tickets > 0) {
            usleep(6000);
            printf("%ld 正在卖第 %d 张门票\n", pthread_self(), tickets);
            tickets--;
        }
        return NULL;
    }
    
    int main() {
    
        // 创建3个子线程
        pthread_t tid1, tid2, tid3;
        pthread_create(&tid1, NULL, sellticket, NULL);
        pthread_create(&tid2, NULL, sellticket, NULL);
        pthread_create(&tid3, NULL, sellticket, NULL);
    
        // 回收子线程的资源,阻塞
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        pthread_join(tid3, NULL);
    
        // 设置线程分离。
        // pthread_detach(tid1);
        // pthread_detach(tid2);
        // pthread_detach(tid3);
    
        pthread_exit(NULL); // 退出主线程
    
        return 0;
    }
    
    • 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

    互斥锁 mutex.c

    /*
        互斥量的类型 pthread_mutex_t
        int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
            - 初始化互斥量
            - 参数 :
                - mutex : 需要初始化的互斥量变量
                - attr : 互斥量相关的属性,NULL
            - restrict : C语言的修饰符,被修饰的指针,不能由另外的一个指针进行操作。
                pthread_mutex_t *restrict mutex = xxx;
                pthread_mutex_t * mutex1 = mutex;
    
        int pthread_mutex_destroy(pthread_mutex_t *mutex);
            - 释放互斥量的资源
    
        int pthread_mutex_lock(pthread_mutex_t *mutex);
            - 加锁,阻塞的,如果有一个线程加锁了,那么其他的线程只能阻塞等待
    
        int pthread_mutex_trylock(pthread_mutex_t *mutex);
            - 尝试加锁,如果加锁失败,不会阻塞,会直接返回。
    
        int pthread_mutex_unlock(pthread_mutex_t *mutex);
            - 解锁
    */
    #include 
    #include 
    #include 
    
    // 全局变量,所有的线程都共享这一份资源。
    int tickets = 1000;
    
    // 创建一个互斥量
    pthread_mutex_t mutex;
    
    void * sellticket(void * arg) {  //该函数是一个线程函数,接收一个void*类型的参数,并返回一个void*类型的指针。
    
        // 卖票
        while(1) {
    
            // 加锁
            pthread_mutex_lock(&mutex);		//通过调用pthread_mutex_lock函数来获取互斥锁。&mutex是互斥锁的地址,用于锁住临界区,保证线程安全
    
            if(tickets > 0) {
                usleep(6000); 				//通过调用usleep函数来使线程暂停6000微秒,相当于6毫秒,模拟卖票的过程。
                printf("%ld 正在卖第 %d 张门票\n", pthread_self(), tickets);		//长整型(long类型)
                tickets--;
            }else {
                // 解锁
                pthread_mutex_unlock(&mutex);
                break;
            }
    
            // 解锁
            pthread_mutex_unlock(&mutex);
        }
    
        
    
        return NULL;
    }
    
    int main() {
    
        // 初始化互斥量
        pthread_mutex_init(&mutex, NULL);
    
        // 创建3个子线程
        pthread_t tid1, tid2, tid3;
        pthread_create(&tid1, NULL, sellticket, NULL);
        pthread_create(&tid2, NULL, sellticket, NULL);
        pthread_create(&tid3, NULL, sellticket, NULL);
    
        // 回收子线程的资源,阻塞
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
        pthread_join(tid3, NULL);
    
        pthread_exit(NULL); // 退出主线程
    
        // 释放互斥量资源
        pthread_mutex_destroy(&mutex);
    
        return 0;
    }
    
    • 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

    在这里插入图片描述
    在这里插入图片描述

    死锁:deadlock1.c

    在这里插入图片描述

    #include 
    #include 
    #include 
    
    // 创建2个互斥量
    pthread_mutex_t mutex1, mutex2;
    
    void * workA(void * arg) {
    
        pthread_mutex_lock(&mutex1);
        sleep(1);
        pthread_mutex_lock(&mutex2);
    
        printf("workA....\n");
    
        pthread_mutex_unlock(&mutex2);
        pthread_mutex_unlock(&mutex1);
        return NULL;
    }
    
    
    void * workB(void * arg) {
        pthread_mutex_lock(&mutex2);
        sleep(1);
        pthread_mutex_lock(&mutex1);
    
        printf("workB....\n");
    
        pthread_mutex_unlock(&mutex1);
        pthread_mutex_unlock(&mutex2);
    
        return NULL;
    }
    
    int main() {
    
        // 初始化互斥量
        pthread_mutex_init(&mutex1, NULL);
        pthread_mutex_init(&mutex2, NULL);
    
        // 创建2个子线程
        pthread_t tid1, tid2;
        pthread_create(&tid1, NULL, workA, NULL);
        pthread_create(&tid2, NULL, workB, NULL);
    
        // 回收子线程资源
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
    
        // 释放互斥量资源
        pthread_mutex_destroy(&mutex1);
        pthread_mutex_destroy(&mutex2);
    
        return 0;
    }
    
    • 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

    读写锁

    在这里插入图片描述
    在这里插入图片描述

    /*
        读写锁的类型 pthread_rwlock_t
        int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
        int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
        int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
        int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
        int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
        int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
        int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
    
        案例:8个线程操作同一个全局变量。
        3个线程不定时写这个全局变量,5个线程不定时的读这个全局变量
    */
    
    #include 
    #include 
    #include 
    
    // 创建一个共享数据
    int num = 1;
    // pthread_mutex_t mutex;
    pthread_rwlock_t rwlock;
    
    void * writeNum(void * arg) {
    
        while(1) {
            pthread_rwlock_wrlock(&rwlock);
            num++;
            printf("++write, tid : %ld, num : %d\n", pthread_self(), num);  //pthread_self()获取当前线程的线程ID
            pthread_rwlock_unlock(&rwlock);
            usleep(100);
        }
    
        return NULL;
    }
    
    void * readNum(void * arg) {
    
        while(1) {
            pthread_rwlock_rdlock(&rwlock);
            printf("===read, tid : %ld, num : %d\n", pthread_self(), num);
            pthread_rwlock_unlock(&rwlock);
            usleep(100);
        }
    
        return NULL;
    }
    
    int main() {
    
       pthread_rwlock_init(&rwlock, NULL);
    
        // 创建3个写线程,5个读线程
        pthread_t wtids[3], rtids[5];
        for(int i = 0; i < 3; i++) {
            pthread_create(&wtids[i], NULL, writeNum, NULL);
        }
    
        for(int i = 0; i < 5; i++) {
            pthread_create(&rtids[i], NULL, readNum, NULL);
        }
    
        // 设置线程分离
        for(int i = 0; i < 3; i++) {
           pthread_detach(wtids[i]);
        }
    
        for(int i = 0; i < 5; i++) {
             pthread_detach(rtids[i]);
        }
    
        pthread_exit(NULL);
    
        pthread_rwlock_destroy(&rwlock);
    
        return 0;
    }
    
    • 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

    生产者与消费者模型

    在这里插入图片描述

    /*
        生产者消费者模型(粗略的版本)
    */
    #include 
    #include 
    #include 
    #include 
    
    // 创建一个互斥量
    pthread_mutex_t mutex;
    
    struct Node{
        int num;
        struct Node *next;
    };
    
    // 头结点
    struct Node * head = NULL;
    
    void * producer(void * arg) {
    
        // 不断的创建新的节点,添加到链表中
        while(1) {
            pthread_mutex_lock(&mutex);
            struct Node * newNode = (struct Node *)malloc(sizeof(struct Node));
            newNode->next = head;
            head = newNode;
            newNode->num = rand() % 1000;
            printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
            pthread_mutex_unlock(&mutex);
            usleep(100);
        }
    
        return NULL;
    }
    
    void * customer(void * arg) {
    
        while(1) {
            pthread_mutex_lock(&mutex);
            // 保存头结点的指针
            struct Node * tmp = head;
    
            // 判断是否有数据
            if(head != NULL) {
                // 有数据
                head = head->next;
                printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
                free(tmp);
                pthread_mutex_unlock(&mutex);
                usleep(100);
            } else {
                // 没有数据
                pthread_mutex_unlock(&mutex);
            }
        }
        return  NULL;
    }
    
    int main() {
    
        pthread_mutex_init(&mutex, NULL);
    
        // 创建5个生产者线程,和5个消费者线程
        pthread_t ptids[5], ctids[5];
    
        for(int i = 0; i < 5; i++) {
            pthread_create(&ptids[i], NULL, producer, NULL);
            pthread_create(&ctids[i], NULL, customer, NULL);
        }
    
        for(int i = 0; i < 5; i++) {
            pthread_detach(ptids[i]);
            pthread_detach(ctids[i]);
        }
    
        while(1) {
            sleep(10);
        }
    
        pthread_mutex_destroy(&mutex);
    
        pthread_exit(NULL);
    
        return 0;
    }
    
    • 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

    条件变量

    /*
        条件变量的类型 pthread_cond_t
        int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr);
        int pthread_cond_destroy(pthread_cond_t *cond);
        int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
            - 等待,调用了该函数,线程会阻塞。
        int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
            - 等待多长时间,调用了这个函数,线程会阻塞,直到指定的时间结束。
        int pthread_cond_signal(pthread_cond_t *cond);
            - 唤醒一个或者多个等待的线程
        int pthread_cond_broadcast(pthread_cond_t *cond);
            - 唤醒所有的等待的线程
    */
    #include 
    #include 
    #include 
    #include 
    
    // 创建一个互斥量
    pthread_mutex_t mutex;
    // 创建条件变量
    pthread_cond_t cond;
    
    struct Node{
        int num;
        struct Node *next;
    };
    
    // 头结点
    struct Node * head = NULL;
    
    void * producer(void * arg) {
    
        // 不断的创建新的节点,添加到链表中
        while(1) {
            pthread_mutex_lock(&mutex);
            struct Node * newNode = (struct Node *)malloc(sizeof(struct Node));
            newNode->next = head;
            head = newNode;
            newNode->num = rand() % 1000;
            printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
            
            // 只要生产了一个,就通知消费者消费
            pthread_cond_signal(&cond);
    
            pthread_mutex_unlock(&mutex);
            usleep(100);
        }
    
        return NULL;
    }
    
    void * customer(void * arg) {
    
        while(1) {
            pthread_mutex_lock(&mutex);
            // 保存头结点的指针
            struct Node * tmp = head;
            // 判断是否有数据
            if(head != NULL) {
                // 有数据
                head = head->next;
                printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
                free(tmp);
                pthread_mutex_unlock(&mutex);
                usleep(100);
            } else {
                // 没有数据,需要等待
                // 当这个函数调用阻塞的时候,会对互斥锁进行解锁,当不阻塞的,继续向下执行,会重新加锁。
                pthread_cond_wait(&cond, &mutex);
                pthread_mutex_unlock(&mutex);
            }
        }
        return  NULL;
    }
    
    int main() {
    
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond, NULL);
    
        // 创建5个生产者线程,和5个消费者线程
        pthread_t ptids[5], ctids[5];
    
        for(int i = 0; i < 5; i++) {
            pthread_create(&ptids[i], NULL, producer, NULL);
            pthread_create(&ctids[i], NULL, customer, NULL);
        }
    
        for(int i = 0; i < 5; i++) {
            pthread_detach(ptids[i]);
            pthread_detach(ctids[i]);
        }
    
        while(1) {
            sleep(10);
        }
    
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
    
        pthread_exit(NULL);
    
        return 0;
    }
    
    
    • 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

    信号量

    /*
        信号量的类型 sem_t
        int sem_init(sem_t *sem, int pshared, unsigned int value);
            - 初始化信号量
            - 参数:
                - sem : 信号量变量的地址
                - pshared : 0 用在线程间 ,非0 用在进程间
                - value : 信号量中的值
    
        int sem_destroy(sem_t *sem);
            - 释放资源
    
        int sem_wait(sem_t *sem);
            - 对信号量加锁,调用一次对信号量的值-1,如果值为0,就阻塞
    
        int sem_trywait(sem_t *sem);
    
        int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
        int sem_post(sem_t *sem);
            - 对信号量解锁,调用一次对信号量的值+1
    
        int sem_getvalue(sem_t *sem, int *sval);
    
        sem_t psem;
        sem_t csem;
        init(psem, 0, 8);
        init(csem, 0, 0);
    
        producer() {
            sem_wait(&psem);
            sem_post(&csem)
        }
    
        customer() {
            sem_wait(&csem);
            sem_post(&psem)
        }
    
    */
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    // 创建一个互斥量
    pthread_mutex_t mutex;
    // 创建两个信号量
    sem_t psem;
    sem_t csem;
    
    struct Node{
        int num;
        struct Node *next;
    };
    
    // 头结点
    struct Node * head = NULL;
    
    void * producer(void * arg) {
    
        // 不断的创建新的节点,添加到链表中
        while(1) {
            sem_wait(&psem);
            pthread_mutex_lock(&mutex);
            struct Node * newNode = (struct Node *)malloc(sizeof(struct Node));
            newNode->next = head;
            head = newNode;
            newNode->num = rand() % 1000;
            printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self());
            pthread_mutex_unlock(&mutex);
            sem_post(&csem);
        }
    
        return NULL;
    }
    
    void * customer(void * arg) {
    
        while(1) {
            sem_wait(&csem);
            pthread_mutex_lock(&mutex);
            // 保存头结点的指针
            struct Node * tmp = head;
            head = head->next;
            printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self());
            free(tmp);
            pthread_mutex_unlock(&mutex);
            sem_post(&psem);
           
        }
        return  NULL;
    }
    
    int main() {
    
        pthread_mutex_init(&mutex, NULL);
        sem_init(&psem, 0, 8);
        sem_init(&csem, 0, 0);
    
        // 创建5个生产者线程,和5个消费者线程
        pthread_t ptids[5], ctids[5];
    
        for(int i = 0; i < 5; i++) {
            pthread_create(&ptids[i], NULL, producer, NULL);
            pthread_create(&ctids[i], NULL, customer, NULL);
        }
    
        for(int i = 0; i < 5; i++) {
            pthread_detach(ptids[i]);
            pthread_detach(ctids[i]);
        }
    
        while(1) {
            sleep(10);
        }
    
        pthread_mutex_destroy(&mutex);
    
        pthread_exit(NULL);
    
        return 0;
    }
    
    
    • 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
  • 相关阅读:
    [人工智能-综述-13]:第九届全球软件大会(南京)有感 -2-新型的云服务:AI即服务,传统的云服务:IaaS,PaaS,SaaS, DaaS
    python输出星期几 青少年编程电子学会python编程等级考试二级真题解析2021年6月
    数据结构 - 二叉树刷题
    【论文阅读】Cornus: Atomic Commit for a Cloud DBMS with Storage Disaggregation
    周期时间计算方法《二》
    Android开发版本和API等级对应关系
    混沌系统在图像加密中的应用(利用DNA编码的图像加密系统)
    Leecode热题100---128:最长连续数列
    【Linux】基础IO
    [附源码]Python计算机毕业设计Django电影院网上售票系统
  • 原文地址:https://blog.csdn.net/weixin_46716100/article/details/132724676