Day27 线程间的锁

一、信号量
信号量(semaphore)是操作系统用来解决并发中的互斥和同步问题的一种方法。

信号量 (个数) --- 反映的是资源的数量

信号量的分类:信号无名量 ==》线程间通信

                         有名信号量 ==》进程间通信

1.信号量的定义 (为全局变量)
sem_t  sem

sem_t:信号量的类型,sem:信号量的变量

例如: sem_t sem_w;,sem_t sem_r;

 
sem_t sem_1;
sem_t sem_2;
2.信号量的初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);

功能:将已经定义好的信号量赋值。

参数:sem 要初始化的信号量,pshared = 0 ;表示线程间使用信号量,!=0 ;表示进程间使用信号量,value 信号量的初始值,一般无名信号量都是二值信号量(0 1) ,0 表示红灯,进程暂停阻塞,1 表示绿灯,进程可以通过执行

返回值:成功  0,失败  -1;

sem_init(&sem_1,0,1);
sem_init(&sem_2,0,0);
3.信号量的PV操作
sem_wait()/ sem_post()

 P ===》申请资源===》申请一个二值信号量int sem_wait(sem_t *sem); 
功能:判断当前sem信号量是否有资源可用。如果sem有资源(==1),则申请该资源,程序继续运行如果sem没有资源(==0),则线程阻塞等待,一旦有资源则自动申请资源并继续运行程序。

注意:sem 申请资源后会自动执行 sem = sem - 1;

参数:sem 要判断的信号量资源

返回值:成功 0 ,失败 -1

 V ===》释放资源===》释放一个二值信号量,nt sem_post(sem_t *sem); 

功能:函数可以将指定的sem信号量资源释放并默认执行,sem = sem+1; 线程在该函数上不会阻塞。

参数:sem 要释放资源的信号量

返回值:成功 0, 失败 -1;

void *doWin2(void *arg)
{
    int i = 0;
    while (1)
    {
        sem_wait(&sem_2);
        if (ticket <= 0)
        {
            sem_post(&sem_1);
            break;
        }
        ticket--; //1 => 0
        printf("win2 sell ticket = %d\n",100-ticket); //100 
        sem_post(&sem_1);
    }
 
    pthread_exit(NULL);
}

4.信号量的销毁
 int sem_destroy(sem_t *sem);

功能:使用完毕将指定的信号量销毁

参数:sem要销毁的信号量

返回值:成功 0,失败  -1;

sem_destroy(&sem_1);
sem_destroy(&sem_2);
二、进程间的通信 
进程创建好之后,父子进程的空间 相互独立 。

1.通信的方式
1、古老的通信方式

管道:无名管道    (1),有名管道    (2)

信号  (3)

2、IPC对象通信 system v    BSD     suse fedora   kernel.org

                          消息队列  (4)

                           共享内存(*) //最高效                (5)

                          信号量集() //信号量                 (6)

3、socket通信

网络通信        (7)

2.管道:  无名管道 
1.int pipe(int pipefd[2]);  
功能:创建一个管道 

参数:pipefd //用来获取 管道的两端 ,读端pipefd[0] ,写端pipefd[1]

返回值:成功 0,失败 -1 && errno  

#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int fd[2];
 
    if (pipe(fd) < 0)
    {
        perror("pipe fail");
        return -1;
    }
    char buf[] = "hello pipe\n";
    write(fd[1],buf,strlen(buf));
    char bufr[100] = {0};
    read(fd[0],bufr,sizeof(bufr));
    printf("bufr = %s\n",bufr);
    return 0;
}

2.管道的特点
管道大小 65536字节   64k 

管道操作特点 ,数据读走之后,认为就没了 

3.管道的读写规则
1.读端存在,写管道

      管道空:可以写数据

      管道满:会造成-->写阻塞 

2.读端不存在,写管道

      系统会给进程发一个信号SIGPIPE(管道破裂)

3.写端存在,读管道

      管道空,读不到数据,

      这时会造成读操作阻塞

4.写端不存在,读管道 

     如果管道中有数据,则读取这些数据!

     如果没有数据,读操作不阻塞,立即返回!

  • 17
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值