zoukankan      html  css  js  c++  java
  • 线程同步、信号量、system v IPC

    一、线程同步
    条件变量
    什么是条件变量?
    线程A等待某个条件成立,条件成立,线程A才继续向下执行。线程B的执行使条件成立,条件成立以后唤醒线程A,以继续执行。这个条件就是条件变量。
    pthread_cond_t  类型   就是条件变量的类型
    对类型的封装如下:
    #include <pthread.h>
    //条件变量的静态初始化
    pthread_cond_t  cond = PTHREAD_COND_INITIALIZER;
    
    int  pthread_cond_init(pthread_cond_t *cond,                 pthread_condattr_t *cond_attr);
    功能:初始化一个条件变量
    参数:
    cond:指定要初始化的条件变量
    cond_attr:NULL   默认属性
    返回值:
    0   成功
    非0   错误
    
    
    int  pthread_cond_signal(pthread_cond_t *cond);
    功能:启动在等待条件变量变为真的一个线程
    参数:
    cond:指定条件变量
    返回值:
    0   成功
    非0   错误
    
    int  pthread_cond_broadcast(pthread_cond_t *cond);
    功能:启动所有的等待条件变量为真的线程
    参数:
    cond:指定条件变量
    返回值:
    0   成功
    非0   错误
    
    int  pthread_cond_wait(pthread_cond_t *cond,                 pthread_mutex_t *mutex);
    功能:等待条件变量为真
    参数:
    cond:指定等待的条件变量
    mutex:等待之前需要解开的锁
    返回值:
    0   成功
    非0   错误
    
    操作步骤:
    1、先原子解mutex锁。
    2、让线程等待条件变量变为真。
    3、条件变量为真的时候,加锁
    
    int pthread_cond_timedwait(pthread_cond_t *cond,
                       pthread_mutex_t  *mutex, 
                 const struct timespec *abstime);
    功能:超时等待,超时返回错误
    参数:
    cond:指定等待的条件变量
    mutex:等待之前需要解开的锁
    abstime:指定等待的时间
    返回值:
    0   成功
    非0   错误
    int  pthread_cond_destroy(pthread_cond_t *cond);
    功能:销毁条件变量
    参数:
    cond:指定要销毁的条件变量
    返回值:
    0   成功
    非0   错误
    
    生产者和消费者的例子
    链表实现    生产者生产出来对象放到链表的头部
                消费者从链表的头部取出消费。
    第一思考:两个线程如何同步访问链表的头部
    第二思考:如果链表为空,消费者等待生产者线程生产对象。
    第三思考:生产者线程,生产出对象通知消费者。
    
    代码参见: cond.c
    
    
    信号量
    多个线程使用多个资源的时候,使用信号量实现线程的同步。
    sem_t类型 
    类型的操作如下:
    sem_init(3)
    #include <semaphore.h>
    int sem_init(sem_t *sem, int pshared, unsigned int value);
    功能:初始化信号量
    参数:
    sem:指定了要初始化的信号量
    pshared:0   应用于多线程   非0   多进程
    value:指定了信号量的初始值
    返回值:
    0  成功
    -1   失败  errno被设置
    
    sem_destroy(3)
    #include <semaphore.h>
    int sem_destroy(sem_t *sem);
    功能:销毁信号量
    参数:
    sem:指定要销毁的信号量
    返回值:
    0  成功
    -1  错误  errno被设置
    
    sem_post(3)
    #include <semaphore.h>
    int sem_post(sem_t *sem);
    功能:信号量的值加1操作
    参数:
    sem:指定的信号量,就是这个信号量的值加1.
    返回值:
    0  成功
    -1   错误  errno被设置
    
    sem_wait(3)
    #include <semaphore.h>
    int sem_wait(sem_t *sem);
    功能:信号量的值减1.如果信号量的值为0.阻塞等待
    参数:
    sem:指定了要操作的信号量
    返回值:
    0  成功
    -1   错误   errno被设置
    int sem_trywait(sem_t *sem);
    
    int sem_timedwait(sem_t *sem, 
        const struct timespec *abs_timeout);
    
    
    使用信号量,实现生产者和消费者的例子
    使用环状队列实现。
    代码参见   sem.c
    
    线程结束了
    
    二、system v IPC
    信号量集
    信号量集就是数组,数组里的每一个元素都是信号量类型的。
    
    1、先获取键值
    ftok(3)
    2、使用键值获取信号量集的id
    semget(2)
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    int semget(key_t  key,  int  nsems, int semflg);
    功能:获取信号量集的id
    参数:
    key:ftok(3)的返回值
    nsems:指定了信号量集中的元素个数
    semflg:
    IPC_CREAT:
    IPC_EXCL:
    mode:指定信号量集的权限
    返回值:
    非负整数,是信号量集的id。
    -1   错误   errno被设置
    
    3、设置信号量集中的信号量的初值或者获取信号量的值。
    semctl(2)
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    int semctl(int semid, int semnum, int cmd, ...);
    功能:信号量的控制操作
    参数:
    semid:指定了信号量集
    semnum:指定了信号量在数组中的下标
    cmd:指定了对信号量的控制操作命令
    GETVAL:获取到第几个信号了的semval值。  semval的值
    SETVAL:设置第几个信号量的semval值为arg.val。 0
    
    ...:可变参数。这个有没有,什么类型?取决于cmd。
    返回值:
    -1   错误  errno被设置
    
    需要自定义
    union semun {
        int        val;    /* Value for SETVAL */
        struct semid_ds *buf; /* Buffer for IPC_STAT,IPC_SET */
        unsigned short  *array; /*Array for GETALL, SETALL */
        struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                     (Linux-specific) */
    };
    
    4、对指定的信号量加法或者减法操作
    semop(2)
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    int semop(int semid, struct sembuf *sops, unsigned nsops);
    功能:信号量操作
    参数:
    semid:指定了信号量集
    sops:指定了对某个信号量的具体操作
    nsops:指定了要操作的信号量的个数。
    
    返回值:
    0   成功
    -1  错误  errno被设置
    
    操作定义在这个结构体中
    struct sembuf{
        unsigned short sem_num;  /* semaphore number */
            short          sem_op;   /* semaphore operation */
            short          sem_flg;  /* operation flags */
    
    };
    sem_flg:
    IPC_NOWAIT  
    IPC_UNDONE  自动撤销操作
    
    sem_num:指定了要操作的信号量在数组的下标
    sem_op:指定了操作的类型
    操作类型分为3种
    >0   semval+sem_op  semval做加法
    =0   
    
    <0:
    semval>sem_op的绝对值,这个操作立即执行。
    
    semval<sem_op的绝对值
    申请的资源数>可用资源数   IPC_NOWAIT  非阻塞
                 sem_flg=0   阻塞等待资源可用
    
    举例说明   使用信号量集实现进程间的通讯。
    两个进程
    PA.c    设置信号量的值 ,每隔3秒,semval的值减1 
    Pb.c    每隔1秒,获取信号量的值,
  • 相关阅读:
    [ABC200E] Patisserie ABC 2
    [CF1521E] Nastia and a Beautiful Matrix
    [CF1498D] Bananas in a Microwave
    [CF1515B] Phoenix and Puzzle
    [CF1519C] Berland Regional
    [CF1519B] The Cake Is a Lie
    [ZONe Energy Programming Contest C] MAD TEAM
    [洛谷P7480] Reboot from Blue
    [CF1508A] Binary Literature
    1371. 货币系统
  • 原文地址:https://www.cnblogs.com/Kernel001/p/7732665.html
Copyright © 2011-2022 走看看