多线程编程之Apue3rd_Chapter15.10之posix信号量
看了APUE的chapter15,只重点看了15.10,学习了posix信号量。Posix信号量比起xsi信号量的优点是性能更好,在Linux3.2.0平台上性能提升很大。其中命名信号量使用方法如下。
1、 头文件#include <semaphore.h>
2、 函数:
(1)sem_t* sem_open(const char * name,int oflag, mode_t mode, unsigned int value)
这个函数是在使用之前先创建信号量,name是你要创建这个命名信号量的字符串名字。Name必须以/开头,并且后面不许再有/。
Oflag一般有两种取值,O-CREAT和O-CREAT|O-EXCL。取值为O-CREAT时候,需要提供全部四个参数的值。如果信号量不存在,则创建一个新的,如果存在,则使用,并没有初始化发生。取值为O-CREAT|O-EXCL时候,也需要提供全部四个参数的值,如果信号量已经存在,sem_open会出错。
mode的值类似Linux文件的权限码。用户读(4)、用户写(2)、用户执行(1),组读(4)、组写(2)、组执行(1),其他读(4)、其他写(2),其他执行(1)。例如网上别人代码的mode取0644,表示当前用户有读写权限,组用户和其他用户只有读权限。(Linux文件的权限修改是chmod 740 文件名,数字前没有0,与这里的不同。可能是命令自动把后面的740当成8进制数来操作。)C程序设计上说,以零开头的是8进制数。网上查网页上说:mode_t是无符号int类型。参考网页---- 《mkdir()函数、mode_t参数》,mkdir和 chmod中的mode也有类似的用法。
如果只使用已存在的命名信号量的值,只要提供name,oflag的值设为0,就可以了。
value是这个这个信号量的初始值,如果是二元信号量的话,一般取1。
函数运行成功的话,会返回一个指向sem_t结构体的指针,这个结构体就是刚刚创建的信号量。出错时返回SEM_FAILED。
sem_open创建的这个sem_t结构体,可能是在内核中开辟的。网上说:有名信号量是随内核持续的,所以如果如果我们不调用sem_unlink来删除它,它将一直存在,直到内核重启(如果一个进程创建了有名信号灯,并退出,那么这个信号灯依然存在)。网上说:有名sem_t是放在文件,无名的sem_t是放在内存。
(2)int sem_wait(sem_t* sem)
创建好信号量之后,如果要获取锁,就使用sem_wait,如果信号量的值此时为0,这个wait会使得当前的wait线程休眠,直到信号量的值为1,当前线程才能被唤醒,从而获取到锁,并执行信号量的值减1动作。
(3)int sem_post(sem_t* sem)
sem_post是释放锁的动作,会使得信号量的值加1,释放当前线程获取到的锁。
(4)int sem_close(sem_t* sem)
如果不使用信号量,需要将其关闭,可能是释放创建信号量时开辟的内存。函数参数是sem_t类型的指针。
(5)int sem_unlink(char* name)
这个函数用于从内核中销毁一个命名信号量。在sem_close执行后执行。
(2)(3)(4)(5)函数如果执行失败,会返回什么样的值,目前还不知道。
下面写一些测试代码:
gcc main.c -o main -lpthread
注意:从word拷贝到txt文本中,双引号的格式不对,需要修改为英文的双引号。需要包含<fcntl.h> ,O_CREAT是在这个文件中定义的。将sem_t*变量设置为全局变量,方便每个线程使用。
测试的时候出现的问题:第一次运行main,运行良好。Ctrl+C结束进程之后,第二次运行main,出现线程死锁现象。原因是,没有执行代码sem_unlink,导致后面重新使用原来存在的命名信号量,但它被之前的进程锁住了,为0。后面的进程想获取锁,就被死锁了。网上资料:进程结束之后,内核不会为进程获取的锁解锁。重启系统(内核),信号量消失,又可以使用了。
解决办法:将子线程的无限循环改为50次循环,从而执行母线程的退出代码:sem_close和sem_unlink,确保退出前销毁信号量。同时在每个线程释放锁之后 ,空循环10000次(10000次才能达到良好效果,5000不保险),使得另外一个线程有足够时间被唤醒,竞争到锁,不至于某个线程一直获取到锁(这个是南京华为的面试官问我的题目:多线程编程有没有遇到某个线程运行速度足够快,从而反复获得锁。我回来测试发现,的确有这种现象)。
修改后的代码放后面。
main.c
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <fcntl.h> //O_CREAT
sem_t* sem1;
sem_t* sem2;
void* thfunc1(void* arg)
{
for(;;)
{
sem_wait(sem1);
printf("This is thread1 printing!\n");
sem_post(sem1);
}
return((void*)0);
}
void* thfunc2(void* arg)
{
for(;;)
{
sem_wait(sem1);
printf("This is thread2 printing!\n");
sem_post(sem1);
}
return((void*)0);
}
int main(int argc,char* argv[])
{
const char* c1 = "/wang_sem1";
int res;
pthread_t tid1,tid2;
void* c;
sem1 = sem_open(c1,O_CREAT,0644,1);
res = pthread_create(&tid1,NULL,thfunc1,NULL);
if(res!=0){
printf("can’t creat thread: %s\n",strerror(res));
}
res = pthread_create(&tid2,NULL,thfunc2,NULL);
if(res!=0){
printf("can’t creat thread: %s\n",strerror(res));
}
pthread_join(tid1,&c);
pthread_join(tid2,&c);
sem_close(sem1);
res = sem_unlink(c1);
if(res!=0)
printf("can’t delete semaphore\n");
return(0);
}
修改后的main.c
#include <semaphore.h>
#include <pthread.h>
#include <stdio.h>
#include <fcntl.h> //O_CREAT
sem_t* sem1;
sem_t* sem2;
void* thfunc1(void* arg)
{
int i,j;
for(i=0;i<50;i++) //for(;;)
{
sem_wait(sem1);
printf("This is thread1 printing!\n");
sem_post(sem1);
for (j=0;j<10000;j++)
{
}
}
return((void*)0);
}
void* thfunc2(void* arg)
{
int i,j;
for(i=0;i<50;i++) //for(;;)
{
sem_wait(sem1);
printf("This is thread2 printing!\n");
sem_post(sem1);
for (j=0;j<10000;j++)
{
}
}
return((void*)0);
}
int main(int argc,char* argv[])
{
const char* c1 = "/wang_sem1";
int res;
pthread_t tid1,tid2;
void* c;
sem1 = sem_open(c1,O_CREAT,0644,1);
res = pthread_create(&tid1,NULL,thfunc1,NULL);
if(res!=0){
printf("can’t creat thread: %s\n",strerror(res));
}
res = pthread_create(&tid2,NULL,thfunc2,NULL);
if(res!=0){
printf("can’t creat thread: %s\n",strerror(res));
}
pthread_join(tid1,&c);
pthread_join(tid2,&c);
sem_close(sem1);
res = sem_unlink(c1);
if(res!=0)
printf("can’t delete semaphore\n");
return(0);
}
多线程编程之Apue3rd_Chapter15.10之posix信号量的更多相关文章
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
- iOS多线程编程之NSThread的使用(转)
本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation ...
- [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...
- [转]iOS多线程编程之NSThread的使用
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS 多线程编程之Grand Central Dispatch(GCD)
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...
- 深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- [Cocoa]深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- [转]c++多线程编程之pthread线程深入理解
多线程编程之pthread线程深入理解 Pthread是 POSIX threads 的简称,是POSIX的线程标准. 前几篇博客已经能给你初步的多线程概念.在进一 ...
- [转] iOS多线程编程之NSOperation和NSOperationQueue的使用
<iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...
随机推荐
- Apache常见问题
Apache如何修改端口? 找到Apache安装目录,conf目录下的httpd.conf文件,用编辑器打开. 找到“Listen 80”,修改为我们想要的端口号就可以了,如“Listen 8080” ...
- mysql使用mysqld_multi工具启动多实例
先给出实验环境/etc/my.cnf文件内容修改内容为:添加了[mysqld_multi]标签和多出来两个数据库的标签[mysqld3307]和[mysqld3308]配置完成后启动方法,举一例:my ...
- chpasswd
功能说明:从标准输入中读取一定格式的用户名.密码来批量更新用户的密码,其格式为 “用户名:密码”. 参数选项:-e 默认格式是明文密码,使用-e参数则需要加密的密码.
- linux下vi的一些简单的操作
前言 在嵌入式linux开发中,进行需要修改一下配置文件之类的,必须使用vi,因此,熟悉 vi 的一些基本操作,有助于提高工作效率. 一,模式 vi编辑器有3种模式:命令模式.输入模式.末行模式.掌握 ...
- What is Thread
A thread is a fundamental unit of CPU utilization –a thread ID –a program counter –a register set –a ...
- Django:模板系统
一,常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 二,常量 {{ 变量名 }} 变量名由字母数字和下划线组成. 点(.)在模板语言中有特殊 ...
- 【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)
点此看题面 大致题意: 给你一个\(01\)串,每次询问前缀编号在一段区间内的两个前缀的最长公共后缀的长度. 离线存储询问 考虑将询问离线,按右端点大小用邻接表存下来(直接排序当然也可以啦). 这样的 ...
- Pod常使用命令
pod 命令汇总 # 创建默认的 Podfile $ pod init # 第一次使用安装框架 $ pod install # 安装框架,不更新本地索引,速度快 $ pod install --no- ...
- html或jsp页面自动提交,无需每次重启服务
从eclipse转到idea遇到各种问题,之前eclipse可以自动保存页面内容无需重启服务,但是idea不可以,网上找了n种办法也没用,可能版本不一样吧,把我的解决方法纪录一下,方便以后有人遇到这个 ...
- 【OJ-UVa227】
耗时一周.哭. 本题重在输入输出.所以对英文题目的理解非常重要.看清楚题目,省时省力. 题目要点: 1.开始有5×5的数据,每行仅有5个字符.注意:样例输入中的尾部空格是无法复制的(UVa官网上),其 ...