文档章节

信号量有没有容量限制?

锟斤拷烫烫烫
 锟斤拷烫烫烫
发布于 07/22 18:25
字数 615
阅读 22
收藏 0

之前一直误以为信号量初始化的时候那个初始化的值是信号量的“容量”,昨天同事指出了我的错误,最初我是不相信的,经过以下代码实践,证明了我的错误:

Java版:

import java.util.concurrent.Semaphore;

public class Driver {

    private Semaphore semaphore;

    public Driver(int num){
        semaphore = new Semaphore(num);
    }

    /**
     * [driveCar description]
     * 假设:我们假定信号量初始化的时候,构造函数中的值是信号量的 容量
     * 验证:如果设置容量为 1 在释放第一次之后 第二次释放将是非法操作 一定会报相关错误
     */

    public void driveCar() {
        try {
            semaphore.acquire();//获取信号量
            int permits = semaphore.availablePermits();//当前可用的信号量
            System.out.println("1permits is "+permits);
            semaphore.release();//释放信号量
            permits = semaphore.availablePermits();
            System.out.println("2permits is "+permits);
            semaphore.release();//再次释放信号量
            permits = semaphore.availablePermits();
            System.out.println("3permits is "+permits);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

编写测试类如下:

class Test {
	public static void main(String[] args) {
		int num = Integer.valueOf(args[0]);
		Driver driver = new Driver(num);
		driver.driveCar();
	}
}

执行测试:java test 1得到结果如下

1permits is 0
2permits is 1
3permits is 2

由此说明,每次信号量释放的时候给信号量的值加1,但是其初始化的值,并不影响这个加1的操作,在 Java 中这个容量固定的假设不成立。

于是我还是不死心,继续去验证了 C 语言版本的,代码如下:

#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
sem_t binSem;
int sval = 0;

int main(int argc,char* argv[])
{
    int res = 0;
    int num = (int)(*argv[1]) - 48;
    printf("num is %d\n",num);
    res = sem_init(&binSem,1,num);
    
    if (res) {
         printf("Semaphore initialization failed!!\n");
         //exit(EXIT_FAILURE);
     }

    sem_wait(&binSem);
    sem_getvalue(&binSem, &sval);
    printf("1permits %d\n",sval);

    sem_post(&binSem);
    sem_getvalue(&binSem, &sval);
    printf("2permits %d\n",sval);

    sem_post(&binSem);
    sem_getvalue(&binSem, &sval);
    printf("3permits %d\n",sval);
}

编译的时候一定要加 -pthread 选项,不然编译会报类似如下错误:


/tmp/cc2tarEg.o: In function `main':
sem.c:(.text+0x51): undefined reference to `sem_init'
sem.c:(.text+0x6e): undefined reference to `sem_wait'
sem.c:(.text+0x7d): undefined reference to `sem_getvalue'
sem.c:(.text+0x9e): undefined reference to `sem_post'
sem.c:(.text+0xad): undefined reference to `sem_getvalue'
sem.c:(.text+0xce): undefined reference to `sem_post'
sem.c:(.text+0xdd): undefined reference to `sem_getvalue'

这里我是这么编译的:gcc sem.c -pthread -o sem

然后执行 ./sem 1

输出:

num is 1
1permits 0
2permits 1
3permits 2

彻底纠正了我一直以来的认知错误。

© 著作权归作者所有

共有 人打赏支持
锟斤拷烫烫烫
粉丝 3
博文 33
码字总数 8049
作品 0
信阳
后端工程师
理解PV操作和信号量

对于信号量,可以认为是一个仓库,有两个概念,容量和当前的货物个数。 P操作从仓库拿货,如果仓库中没有货,线程一直等待,直到V操作,往仓库里添加了货物,为了避免P操作一直等待下去,会有...

抢地主
2016/06/23
28
0
【PHP】如何优雅的杀死PHP的死循环(常驻进程)

在日常开发的过程中,遇到一个问题,就是 有这么一个常驻进程,每隔6秒,干一些事情,这个时候,突然出了一些意外状况或者要迭代版本,得先给这个进程停掉,打断循环退出。如果直接kill掉,那...

qq_28602957
2017/10/31
0
0
zephyr笔记 2.4.1 信号量

1 前言 信号量是实现传统计数信号量的内核对象。 我正在学习 Zephyr,一个很可能会用到很多物联网设备上的操作系统,如果你也感兴趣,可点此查看帖子zephyr学习笔记汇总。 2 概念 可以定义任...

iotisan
04/28
0
0
swoole 中的锁及其应用

date: 2017-12-25 01:42:00 title: swoole 中的锁及其应用 时间不早了, 尽量言简意赅一些. 怎么快速学习锁: 锁是什么 -> 锁的概念 为什么要用锁 -> 锁的使用场景 怎么使用锁 -> show me the...

daydaygo
2017/12/26
0
0
第15章 进程间通行 15.6 XSI IPC 15.7 消息队列

15.6 XSI IPC (1)3种称作XSI IPC的IPC是: 1)消息队列 2)信号量 3)共享存储器 (2)标识符和键 1)标识符:是一个非负整数,用于引用IPC结构。是IPC对象的内部名。 2)键:IPC对象的外部...

fxdhdu
2015/10/23
79
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周日乱弹 —— 小心着凉 @红薯

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:5.33起,其声呜呜然,如怨如慕,如泣如诉。余音袅袅,不绝如缕。分享Arch Enemy的单曲《Bridge Of Destiny (2009)》 《Bridge Of...

小小编辑
今天
271
4
what f,,

anlve
今天
9
0
初级开发-编程题

` public static void main(String[] args) { System.out.println(changeStrToUpperCase("user_name_abc")); System.out.println(changeStrToLowerCase(changeStrToUpperCase("user_name_abc......

小池仔
今天
15
0
现场看路演了!

HiBlock
昨天
23
0
Rabbit MQ基本概念介绍

RabbitMQ介绍 • RabbitMQ是一个消息中间件,是一个很好用的消息队列框架。 • ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的s...

寰宇01
昨天
18
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部