zoukankan      html  css  js  c++  java
  • C系统编程之生产者与消费者

    锁可以实现互斥,条件变量可以实现同步。

    为了保护共享数据的正确性,我们需要把锁和条件变量联合起来使用,这就是 管程(Monitor) 的作用。

    管程将需要保护的一组共享数据封装起来,利用锁与条件变量实现对这些数据的保护,保证同时只有一个函数能够使用这组数据。

    对于一个栈(Stack)数据结构来说,如果在多线程的情况下实现 push()pop() 功能,程序就会变得不安全 —— 在一个线程正在调用 push() 时,如果内核切换到另一个线程,另一个线程运行 pop(),那么就可能出现多种不同的结果;更糟糕的是,如果栈里只剩下一个元素,此时有两个线程调用 pop(),我们可能会在两个线程中获得同一个元素。为了避免这种不安全因素,我们利用管程来保护栈的内部状态。

    示例程序:

    #include <stdlib.h>
    #include <pthread.h>
    
    struct stack_entry {
        void *data;
        struct stack_entry *next;
    };
    
    struct stack {
        struct stack_entry *head;
        int capacity;
        int count;
        pthread_mutex_t mutex;
        pthread_cond_t is_full;
        pthread_cond_t is_empty;
    };
    
    struct stack *new_stack(int capacity) {
        struct stack *my_stack = calloc(1, sizeof(struct stack));
        if (my_stack == NULL) {
            return NULL;
        }
        my_stack->head = NULL;
        my_stack->capacity = capacity;
        my_stack->count = 0;
        pthread_mutex_init(&my_stack->mutex, NULL);
        pthread_cond_init(&my_stack->is_full, NULL);
        pthread_cond_init(&my_stack->is_empty, NULL);
        return my_stack;
    }
    
    int push(struct stack *my_stack, void *data) {
        if (pthread_mutex_lock(&my_stack->mutex) != 0) {
            return -1;
        }
        while (my_stack->count == my_stack->capacity) {
            pthread_cond_wait(&my_stack->is_full, &my_stack->mutex);
        }
        struct stack_entry *new_entry = calloc(1, sizeof(struct stack_entry));
        if (new_entry == NULL) {
            return -1;
        }
        new_entry->data = data;
        new_entry->next = my_stack->head;
        my_stack->head = new_entry;
        my_stack->count += 1;
        pthread_cond_signal(&my_stack->is_empty);
        if (pthread_mutex_unlock(&my_stack->mutex) != 0) {
            return -1;
        }
        return 0;
    }
    
    void *pop(struct stack *my_stack) {
        if (pthread_mutex_lock(&my_stack->mutex) != 0) {
            return (void *)-1;
        }
        while (my_stack->count == 0) {
            pthread_cond_wait(&my_stack->is_empty, &my_stack->mutex);
        }
        struct stack_entry *top = my_stack->head;
        my_stack->head = top->next;
        void *data = top->data;
        free(top);
        my_stack->count -= 1;
        pthread_cond_signal(&my_stack->is_full);
        if (pthread_mutex_unlock(&my_stack->mutex) != 0) {
            return (void *)-1;
        }
        return data;
    }
    
    int main() {
        return 0;
    }
    
  • 相关阅读:
    Java中获取键盘输入值的三种方法
    java多线程处理与数据集合
    Apachetomcat学习
    Java之枚举
    多例设计模式与枚举
    权限管理(数据库部分)
    hdu 2458(最大独立集)
    hdu 1507(最大匹配)
    hdu 1350+hdu 1960(最小路径覆盖)
    hdu 1845(最大匹配)
  • 原文地址:https://www.cnblogs.com/quanjun/p/14623845.html
Copyright © 2011-2022 走看看