0

Image Description

荆文征

Zhidu Inc.


你好,再见

Pthreads 学习3 - 信号量

  • 小酒馆老板
  • /
  • 2018/1/11 23:22:0

锁,在多个线程中一起访问同一个属性,如果不加锁的话,会导致数据出现错误。

举一个最简单的例子,又一个 int 类型的公共变量 值为 0,2个线程同时访问他,都做10次累加。那么极有可能会出现,这个值不等于20的情况。
这种时候就需要锁这种东西,我觉的锁,其实和信号量还是挺像的,感觉像信号量的进阶?

以下为5种方式
.
├── MutexForInType.cpp
├── MutexForOutType.cpp
├── NoLockType.cpp
├── SemaphoreForInType.cpp
└── SemaphoreForOutType.cpp


H3

使用信号量来进行这个测试

好吧,用了半个小时才搞完这个计算平均时间的小东西。。。

var res = "1.[0.058362]<br/>2.[0.058790]<br/>3.[0.055453]<br/>4.[0.058895]<br/>5.[0.055795]<br/>6.[0.063488]<br/>7.[0.064370]<br/>8.[0.057868]<br/>9.[0.058790]<br/>10.[0.056153]";
var cal = /[0-9.]+\[([0-9.]+)\]/g;
var m;

var sum = 0;
var count = 0;

do{
  m = cal.exec(res);
  if (m) {
    sum+=parseFloat(m[1]);
    count++;
    console.log(m[1],sum,count);
  }
}while(m);

console.log(sum/count);
我就一展示数据的表格
名称 线程安全 成绩 平均分
MutexForInType 1.[0.202137]
2.[0.185789]
3.[0.179368]
4.[0.272630]
5.[0.239758]
6.[0.240693]
7.[0.255223]
8.[0.198637]
9.[0.232774]
10.[0.248535]
0.22555439999999996
MutexForOutType 1. [0.058362]
2.[0.058790]
3.[0.055453]
4.[0.058895]
5.[0.055795]
6.[0.063488]
7.[0.064370]
8.[0.057868]
9.[0.058790]
10.[0.056153]
0.058796400000000006
NoLockType 1.[0.281418]
2.[0.273135]
3.[0.264430]
4.[0.266663]
5.[0.190819]
6.[0.198963]
7.[0.221909]
8.[0.240771]
9.[0.245478]
10.[0.293448]
0.24770340000000002
SemaphoreForInType 1.[0.321427]
2.[0.270053]
3.[0.312442]
4.[0.321051]
5.[0.252933]
6.[0.237228]
7.[0.293928]
8.[0.254666]
9.[0.275634]
10.[0.291737]
0.2831099
SemaphoreForOutType 1.[0.062282]
2.[0.066465]
3.[0.056639]
4.[0.047239]
5.[0.064882]
6.[0.058525]
7.[0.062361]
8.[0.058302]
9.[0.058728]
10.[0.055138]
0.0590561

H3

关于 sem_open 方法传参问题

运行 man sem_open 得到以下,还是不清楚他是如何穿参数的,我们只是知道了 oflag 有两个参数。 O_CREAT O_EXCL。 但是 oflag.是一个可变参数,他到底是什么呢?

IBM Knowledge Center - sem_open()–Open Named Semaphore找到了一些说法,也就是说,三个参数。


H4

name

指向要打开的信号量的以空字符结尾的名称的指针。 该名称应以斜线(’/‘)字符开头。 如果名称不以斜杠(’/‘)字符开始,则系统会在名称的开头添加一个斜杠。
假设这个参数在当前对作业有效的CCSID(编码字符集标识符)中表示。 如果作业的CCSID是65535,则假定此参数在作业的默认CCSID中表示。

该名称被添加到仅由命名信号量使用的一组名称中。 名称与任何文件系统路径名都没有关系。 名称的最大长度是SEM_NAME_MAX


H4

oflag

oflag
选项参数。
oflag参数值为零,或者通过对以下一个或多个常量执行OR运算来获得:

我就一展示数据的表格
可选项 解释
‘0x0008’ or O_CREAT 如果不存在,则创建指定的信号量。
‘0x0010’ or O_EXCL 如果O_CREAT也被设置并且指定的信号量已经存在,则会导致sem_open()失败。

H4

mode

权限标志。
模式参数值可以是零,也可以通过对以下一个或多个常量列表执行OR操作来获得。 对于另一个打开信号量的进程,进程的有效UIDd必须能够以读写模式打开信号量。

我就一展示数据的表格
可选项 解释
‘0x0100’ or S_IRUSR 允许指定信号量的创建者以读取模式打开信号量。
‘0x0080’ or S_IWUSR 允许指定信号量的创建者在写入模式下打开信号量。
‘0x0020’ or S_IRGRP 允许与指定信号相关联的组以打开信号量的读取模式。
‘0x0010’ or S_IWGRP 允许与指定信号相关联的组以打开信号量的写入模式。
‘0x0004’ or S_IROTH 允许其他人以读取模式打开指定的信号量。
‘0x0002’ or S_IWOTH 允许其他人在写入模式下打开指定的信号量。.

H4

value

指定信号量的初始值。

如果感兴趣可以直接去查看源码 sem_open.c


H3

关于有名信号量和无名信号量

一开始觉的这是什么,,,,感觉很难啊,,,
当我开始做的时候,发现,sem_init在OSX系统上被弃用了,,, 只能用,sem_open打开,而使用这个方法,我们也都讨论过了,需要传入一个名称。

至此,,,,,原来这就是有名 无名,,,还真是贴切….


H3

锁和信号量的区别

我个人觉的 锁是针对 多个线程访问 公共变量的时候为了防止同步出现错误而进行的保护操作。而信号量则是一个交流吧?
就是比如说 A线程和B线程都去找个妹子,A线程找到的时候,因为妹子没空,B线程只能等待。等到A线程约会完之后,妹子被释放,B线程才可以被访问。
而信号量,则是说,咱们用别人都用的开灯关灯来说比较好。信号灯! 没有量的时候,B线程就一直等着,等到A亮灯,B就知道了~ 哦哦哦· 该我了~
这样子….

以下说一下大家都说的几个区别。

  1. 互斥量用于线程的互斥,信号线用于线程的同步。
  2. 互斥量值只能为0/1,信号量值可以为非负整数。
  3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
专栏: 线程
标签: IOS Pthreads 线程