操作系統經典同步互斥問題——生產者消費者問題


linux下的同步和互斥

tags: Linux sync_mutex

Semaphore.h

一份好文檔,勝讀十年書

本文參考了諸多資料,百度百科,cplusplus等

首先介紹一個頭文件
#include <semaphore.h>

這里面包含了大多數的所需要使用的信號量.
包含:

  • int sem_init(sem_t *sem, int pshared, unsigned int value)
    用於初始化信號量。
    value代表信號量的初始值,
    pshare代表信號量是進程內的線程共享,還是進程間共享。

對於Linux而言,就是子進程共享和父進程共享——Linux中不存在線程的問題,Linux中的線程,進程均為進程,只是看進程組,子進程父進程而已。對於進程關系,可以使用pstree查看。

返回0時成功,返回-1時失敗,並且設置errno
使用perror輸出錯誤信息:
- EINVAL
value 超過 `SEM_VALUE_MAX`
- ENOSYS
pshared 非零,但系統還沒有支持進程共享的信號量。
  • int sem_post(sem_t *sem)
    這個函數相當於V操作,是一個"原子操作"——即是不會被打斷(中斷)的。並行計算中會出現的兩個線
    程同時對一個變量相加導致變量的值僅產生了一次變化在此處是不成立的。
    返回0時成功,返回-1時失敗, 並且設置errno:

    • EINVAL
      sem 不是一個有效的信號量。
    • EOVERFLOW
      信號量允許的最大值將要被超過。
  • int sem_wait(sem_t *sem)
    這個函數相當於P操作,也是一個"原子操作"。等待對變量-1,如果不能對變量-1,則進入等待隊列

  • int sem_trywait(sem_t *sem)
    如果變量不能-1(即sem_t為0),則不會進入等待隊列,直接返回錯誤代碼。

  • int sem_timedwait(sem_t *sem)

  • int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

  • return 0 (success), return -1 (failure) and set errno:
    - EINTR
    The call was interrupted by a signal handler; see signal(7).
    //調用被信號處理中斷
    - EINVAL sem is not a valid semaphore.
      //sem不是有效的信號量
    The following additional error can occur for sem_trywait():
      //下面的錯誤是sem_trywait()可能發生的:
    - EAGAIN The operation could not be performed without blocking (i.e., the
      semaphore currently has the value zero).
      //除了鎖定無法進行別的操作(如信號量當前是0值).
    The following additional errors can occur for sem_timedwait():
      //下面的錯誤是sem_timedwait()可能發生的:
    - EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than or
      equal to 1000 million.
      //abs_timeout.tv_nsecs 的值比0小或者大於等於1000毫秒(譯者注:納秒的值不能比0小,不能比1秒大)
    - ETIMEDOUT
      The call timed out before the semaphore could be locked.
      //在信號量鎖定之前就超時了
    - 注意
    對這些函數,信號處理程序總是會中斷阻塞,不管是否使用了sigaction(2)的SA_RESTART標志位.
/*=============================================================================
#
# Author: svtter - svtter@qq.com
#
# QQ : 57180160
#
# Last modified: 2014-10-03 20:35
#
# Filename: producer_consumer.cc
#
# Description: 
#
=============================================================================*/
#include <cstdio>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
#include <sys/types.h>
#include <stdlib.h>
#include <iostream>

using namespace std;

#define N 5
#define item int

// P/V操作
void P(sem_t* sem)
{
    if(sem_wait(sem))
        perror("P error!");
    
}

void V(sem_t* sem)
{
    if(sem_post(sem))
        perror("V error!");
}

sem_t mutex;
sem_t full;
sem_t empty;
item buffer[N];
int i = 0, j = -1;

void init_sem()
{
    sem_init(&mutex, 0, 1);
    sem_init(&full, 0, 0);
    sem_init(&empty, 0, N);
}

void* producer(void *arg)
{
    int product;
    while(1)
    {
        //生成隨機數字
        product = rand()%100;
        // cout << "producer running..." << endl;
        P(&empty);
        P(&mutex);
        buffer[i] = product;
        printf("producer produced %d @ %d pos\n",
                product, i);
        i=(i+1)%N;
        V(&mutex);
        V(&full);
        sleep(1);
    }
}

void* consumer(void *arg)
{
    int product, temp;
    while(1)
    {
        // cout << "consumer running..." << endl;
        P(&full);
        P(&mutex);
        j = (j+1)%N;
        product = buffer[j];
        V(&mutex);
        V(&empty);
        printf("Consumer consumed %d @ %d pos\n",
                product, j);
        sleep(3);
    }
}

int main()
{
    //random num
    srand(time(NULL));
    init_sem();
    
    int error;
    pthread_t producer_t, consumer_t;

    error = pthread_create(&producer_t, NULL, producer, NULL);
    if(error != 0)
        printf("error in create producer.\n");
    else
        printf("create producer success!\n");

    pthread_create(&consumer_t, NULL, consumer, NULL);
    if(error != 0)
        printf("error in create consumer.\n");
    else
        printf("create consumer success!\n");
    
    pthread_join(producer_t, NULL);
    pthread_join(consumer_t, NULL);

    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM