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;
    }
    
  • 相关阅读:
    Mac 10.13安装telnet
    如何用万用表判断一个12V蓄电池是否没电
    CentOS 7开机不执行/etc/rc.local的解决方法
    华为S5300系列交换机限制特定IP可以登录Web
    Java Bean Validation 最佳实践
    一文说清文本编码那些事
    定义物料组(Material Group)
    kibana 搜索语法
    微服务相关
    Solve Error: nafxcw.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new[](unsigned int)" (??_U@YAPAXI@Z) already defined in libcpmt.lib(newaop.obj)
  • 原文地址:https://www.cnblogs.com/quanjun/p/14623845.html
Copyright © 2011-2022 走看看