spinspin lock bh和 Semaphore信号量的区别

博客访问: 1025665
博文数量: 89
博客积分: 1205
博客等级: 少尉
技术积分: 4304
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: LINUX
关于Linux内核中的mutex机制,一篇很重要的文档来自内核源码中的Documentation/mutex-
design.txt,由Ingo molnar同学起头,标题是"Generic Mutex
Subsystem",这篇文档开宗名义,直接将1楼中最后一个问题给端了出来(因此我估计这个问题此前已经有很多人骚扰过Ingo等同学了):
"Why on earth do we need a new mutex subsystem, and what's wrong with semaphores?"
前面已经讲过,当struct
semaphore中的成员变量为1,就可以用来实现mutex这种东西,而且内核也明确定义了DEFINE_SEMAPHORE宏将count初始化为
1,信号量上的DOWN与UP操作就更不用说了,在内核中也都有很好的实现,难道这种binary
semaphore机制还不能满足我们的要求吗,干嘛还非得弄一个新的mutex机制出来呢?
下面是Ingo同学对此的解释,他说“firstly, there's nothing wrong with semaphores. But if
the simpler mutex semantics are sufficient for your code, then there
are a couple of advantages of
mutexes”,就是说,信号量在Linux中的实现是没任何问题的(上来先安抚一下大家躁动的心情),但是mutex的语义相对来说要较信号量要来得
简单,所以如果你的代码若只是想对某一共享资源进行互斥访问的话,那么使用这种简化了的mutex机制可以带来如下的一坨好处。这句话字面上的理解
是,mutex将binary semaphore的实现简化了(the simper
mutex),因此如果单纯从互斥的角度,用mutex会有很多好处。
其实后面我们会看到,在内核源码中,相对于semaphore的DOWN和UP实现,因为后期引入的特别针对binary
semaphore的性能优化,也就是现在看到的mutex机制,其实现代码要更为复杂。
接下来Ingo列出的一大堆使用mutex的好处,在这个帖子中我们将一条一条地来看,再结合内核源码,看看事实是否的确象他说的那样:
- 'struct mutex' is smaller on most architectures: E.g. on x86, 'struct
semaphore' is 20 bytes, 'struct mutex' is 16 bytes. A smaller structure
size means less RAM footprint, and better CPU-cache utilization.
这条最好验证,尤其还是x86平台,找个简单的内核模块,打印一下sizeof就可以了。在我的x86-64
32位Linux系统(内核版本2.6.37)上, struct semaphore的大小是16字节,而struct
mutex的大小则是20字节,另两台x86-64 64位Linux系统(内核版本3.x)上的结果则是,struct
semaphore的大小是24字节,而struct mutex的大小则是32字节。这里不妨看一下struct mutex在内核中的定义:struct mutex {&&&&&&&&/* 1: unlocked, 0: locked, negative: locked, possible waiters */&&&&&&&&atomic_t
count;&&&&&&&&spinlock_t
wait_lock;&&&&&&&&struct list_head
wait_list;#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)&&&&&&&&struct task_struct
*owner;#endif#ifdef CONFIG_DEBUG_MUTEXES&&&&&&&&const char
*name;&&&&&&&&void
*magic;#endif#ifdef CONFIG_DEBUG_LOCK_ALLOC&&&&&&&&struct lockdep_map
dep_map;#endif};可以看到stuct mutex的定义其实比semaphore要来得复杂,里面有一些条件编译选项在里面。因为我们实际使用当中很少会使用它的调试功能,但是SMP现在则很普遍,我上面测试用的Linux环境都是多处理器系统。所以,mutex的定义实际上可简化为:struct mutex {&&&&&&&&/* 1: unlocked, 0: locked, negative: locked, possible waiters */&&&&&&&&atomic_t
count;&&&&&&&&spinlock_t
wait_lock;&&&&&&&&struct list_head
wait_list;&&&&&&&&struct task_struct
*owner;};对比一下前面struct semaphore的定义你会发现,struct
mutex比semaphore多了一个owner指针,因此上面的结果也就不难理解了,指针在32位系统上是4字节,而64位系统则是8字节。我相信
Ingo同学肯定不会胡说八道,那么明显地,相对于Ingo当时写mutex-design.txt时的情形,Linux内核源码发生了变化,这个在
Linux的开发过程中实在是太正常不过的一件事了:文档总是远远落后于代码的更新--大家都忙着写code,而很少有人想着去更新文档。
所以接下来Ingo提到的tighter code的优势,估计对mutex而言也不复存在了...
(他本人对mutex相对于semaphore在RAM footprint方面的优势不复存在的最新回复是:"Mutex got larger
due to the adaptive spin-mutex performance
optimization",因此我很自然地将这句话理解成,由于要实现所谓的“adaptive spin-mutex performance
optimization",那么就不惜牺牲了"less RAM footprint, and better CPU-cache
utilization",所以我们有理由期待接下来的spin-mutex performance
optimization会给mutex带来性能上比较大的提升...)下面我们来讨论一下mutex所做的性能优化,在将mutex的引入Linux内核这件事上,Ingo同学是带头大哥,喜欢围观Linux内核开发的同学对这厮肯定不会陌生,在我看来,这厮简直是牛逼得一塌糊涂,将kgdb引入内核也是这厮的杰作...
在mutex的性能提升方面,mutex-design.txt文档中有个具体的测试,采用了一个test-mutex的工具,因为google没找到这
个东西,所以我个人猜测是Ingo自己搞出来的东西,本来想趁这两天放假将最新版下的binary
semaphore和mutex的性能测试一把的,结果这两天啥都没干成。我本来是想索要那个test-mutex程序的,但是Ingo只是建议采用
perf来做。我自己找了个sysbench,但是还没时间用,貌似这个是针对数据库的。之所以做这个测试,是我想知道采用mutex到底能比
binary semaphore能带来多大的性能提升。
按照Ingo的测试数据,"the mutex based kernel was 2.4 times faster than the
semaphore based kernel, _and_ it also had 2.8 times less CPU
utilization",因为事先看过mutex的实现源码,所以我对这个数据有点怀疑,这也是为什么我自己要做性能分析的原因。
semaphore和mutex的代码实现中都有fast path和slow path两条路径,所谓的fast
path,就是当前的代码直接获得信号量,而所谓的slow path,则是当前代码没能第一时间获得信号量。semaphore和mutex在fast
path上性能上的变化应该微乎其微,这个在metex-design.txt文档中也有说明。两者之间最大的差别来自对slow
path的处理,先看semaphore,semaphore的slow
path的调用链是down_interruptible-->__down_interruptible -->
__down_common,&&__down_common的代码实现为:static inline int __sched __down_common(struct semaphore *sem, long state,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&long timeout){&&&&&&&&struct task_struct *task = current;&&&&&&&&struct semaphore_waiter waiter;&&&&&&&&list_add_tail(&waiter.list, &sem->wait_list);&&&&&&&&waiter.task = task;&&&&&&&&waiter.up = 0;&&&&&&&&for (;;) {&&&&&&&&&&&&&&&&if (signal_pending_state(state, task))&&&&&&&&&&&&&&&&&&&&&&&&goto interrupted;&&&&&&&&&&&&&&&&if (timeout <= 0)&&&&&&&&&&&&&&&&&&&&&&&&goto timed_out;&&&&&&&&&&&&&&&&__set_task_state(task, state);&&&&&&&&&&&&&&&&raw_spin_unlock_irq(&sem->lock);&&&&&&&&&&&&&&&&timeout = schedule_timeout(timeout);&&&&&&&&&&&&&&&&raw_spin_lock_irq(&sem->lock);&&&&&&&&&&&&&&&&if (waiter.up)&&&&&&&&&&&&&&&&&&&&&&&&return 0;&&&&&&&&}&timed_out:&&&&&&&&list_del(&waiter.list);&&&&&&&&return -ETIME;&interrupted:&&&&&&&&list_del(&waiter.list);&&&&&&&&return -EINTR;}相对mutex对slow
path的处理,semaphore要简单多了,它的主要流程是设置当前进程状态为TASK_INTERRUPTIBLE,然后睡眠到一个等待队列中。所
以semaphore如果第一时间没有获得信号量,那么它接下来就会sleep。但是mutex的slow
path呢,所有关于性能优化的代码都集中在该条路径中,所有它看起来比semaphore复杂许多...
阅读(6353) | 评论(2) | 转发(11) |
相关热门文章
给主人留下些什么吧!~~
我也感觉好运,呵呵
本人感觉mutex好用啊~~可能是习惯原因吧~嘎嘎
请登录后评论。新手园地& & & 硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD& & & BSD文档中心AIX& & & 新手入门& & & AIX文档中心& & & 资源下载& & & Power高级应用& & & IBM存储AS400Solaris& & & Solaris文档中心HP-UX& & & HP文档中心SCO UNIX& & & SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术& & & 服务器资源下载云计算& & & 云计算文档中心& & & 云计算业界& & & 云计算资源下载存储备份& & & 存储文档中心& & & 存储业界& & & 存储资源下载& & & Symantec技术交流区安全技术网络技术& & & 网络技术文档中心C/C++& & & GUI编程& & & Functional编程内核源码& & & 内核问题移动开发& & & 移动开发技术资料ShellPerlJava& & & Java文档中心PHP& & & php文档中心Python& & & Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL& & & MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯& & & 猎头招聘IT图书与评论& & & CU技术图书大系& & & Linux书友会二手交易下载共享Linux文档专区IT培训与认证& & & 培训交流& & & 认证培训清茶斋投资理财运动地带快乐数码摄影& & & 摄影器材& & & 摄影比赛专区IT爱车族旅游天下站务交流版主会议室博客SNS站务交流区CU活动专区& & & Power活动专区& & & 拍卖交流区频道交流区
白手起家, 积分 1, 距离下一级还需 199 积分
论坛徽章:0
看了好多关于semphore completion的描述中,似乎都是要A线程 要等待 B线程工作完成后 才能继续执行。 不太理解书上为何讲使用completion 比 semaphore 更好?&&求指点。
&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp&&nbsp|&&nbsp
白手起家, 积分 168, 距离下一级还需 32 积分
论坛徽章:1
我猜semaphore和mutex一样都是同步用的,开销应该要比completion机制大一些。
论坛徽章:9
有非常详细的说明。连引入的历史都给你了。
论坛徽章:9
There are two reasons you might want to use a completion instead of a semaphore. First, multiple threads can wait for a completion, and they can all be released with one call to complete_all(). It's more complex to have a semaphore wake up an unknown number of threads.
Second, if the waiting thread is going to deallocate the synchronization object, there is a race condition if you're using semaphores. That is, the waiter might get woken up and deallocate the object before the waking thread is done with up(). This race doesn't exist for completions. (See Lasse's post.)
论坛徽章:9
Explanation of why completions were originally implemented:
The basic summary is that we had this (fairly common) way of waiting for certain events by having a locked semaphore on the stack of the waiter, and then having the waiter do a &down()& which caused it to block until the thing it was waiting for did an &up()&.
This works fairly well, but it has a really small (and quite unlikely) race on SMP, that is not so much a race of the idea itself, as of the implementation of the semaphores. We could have fixed the semaphores, but there were a few reasons not to:
the semaphores are optimized (on purpose) for the non-contention case. The &wait for completion& usage has the opposite default case
the semaphores are quite involved and architecture-specific, exactly
due to this optimization. Trying to change them is painful as hell.
So instead, I introduced the notion of &wait for completion&:
More recent thread about completions vs semaphores
丰衣足食, 积分 677, 距离下一级还需 323 积分
论坛徽章:7
That is, the waiter might get woken up and deallocate the object before the waking thread is done with up().
这句好难理解。
论坛徽章:9
被woken up的线程可能立即把对应的锁的空间释放,但waking 它的线程的up函数需要访问这个空间,这样就会崩溃。内核的代码里有大量的completions都是定义成局部变量的,如果改为信号量,就会出现这种情况。有个CSDN的网友也进行了说明,见:
同时,completion比semaphore要轻量运行得快,他两个有一个本质的差别。
一个是有信号量,有数量的概论,数量不够了才睡。
一个是完成量,大家都等同一条件,没有数量的差异。
丰衣足食, 积分 677, 距离下一级还需 323 积分
论坛徽章:7
本帖最后由 smalloc 于
01:38 编辑
& & CSDN上这个解释非常怪异,
谈的大致流程可认为:
B down 获得semaphore
A down sleep
B up start
也就是认为B up end 有段代码在A down up后还会去访问semaphore.
但从代码看显然不是这样。所有访问semaphore的操作都是用 spinlock_irq保护的原子操作。void up(struct semaphore *sem)
{
& & & &
& & & & spin_lock_irqsave(&sem-&lock, flags);
& & & & if (likely(list_empty(&sem-&wait_list)))
& & & & & & & & sem-&count++;
& & & & else
& & & & & & & & __up(sem);
& & & & spin_unlock_irqrestore(&sem-&lock, flags);
}
复制代码这意味着从全局域角度看时序,A的down 完成也只能在B up之后
论坛徽章:9
技术是不断在往前发展的。要从历史的角度去看代问题,所有事情事出必有因。
引入completion时(应该是2.4.7版本)的semaphore确实存在问题,问题模型为:
,google上应该还有其它的邮件。
那时的semaphore是没有锁保护的。到少我手上2.6.24的源码里就没有。
现在semaphore已经没有问题了。甚至有人还提议用semaphore从新实现completion:
从git来看,最终社区并没有接纳。
现在高版本的semaphore 已经不存在问题了。只是从概念层面,completion 和semaphore 应该被用来不同的场合,completion 是用来等待一个条件成力,而semaphore应该是等待一个资源。条件是没有数量的,而资源是有数量的。
从实现来说,completion更轻(我没有验正过)
请在里搜lightweight。
稍有积蓄, 积分 210, 距离下一级还需 290 积分
论坛徽章:0
这样的讨论真的很有价值 么么哒
北京盛拓优讯信息技术有限公司. 版权所有 京ICP备号 北京市公安局海淀分局网监中心备案编号:22
广播电视节目制作经营许可证(京) 字第1234号
中国互联网协会会员&&联系我们:
感谢所有关心和支持过ChinaUnix的朋友们
转载本站内容请注明原作者名及出处原子操作、信号量、读写信号量和自旋锁的区别与联系_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
原子操作、信号量、读写信号量和自旋锁的区别与联系
&&原子操作、信号量、读写信号量和自旋锁的区别与联系
你可能喜欢最近的多线程 想实现这样的功能: 多线程Socket获得的数据 对其进行某种处理FuncA,但是FuncA比较耗时,希望能够单独独立出来,这样 接受和处理数据分开,但是FuncA处理数据不能放入一个线程,否则很慢,要多线程处理,这个时候 就要使用 多线程 信号量 semaphore了。【我是在windows下 使用pthread win32 的】
在pthread win32源码中,semaphore.h是这样定义的:
typedef struct sem_t_ * sem_t;
下面是这个结构的定义
* ====================
* ====================
* Semaphores, Mutexes and Condition Variables
* ====================
* ====================
struct sem_t_
pthread_mutex_t lock;
#if defined(NEED_SEM)
int leftToU
其方法有:
int sem_init (sem_t * sem,int pshared,unsigned int value);
int sem_destroy (sem_t * sem);
int sem_trywait (sem_t * sem);
int sem_wait (sem_t * sem);
int sem_timedwait (sem_t * sem,const struct timespec * abstime);
int sem_post (sem_t * sem);
int sem_post_multiple (sem_t * sem,int count);
int sem_getvalue (sem_t * sem,int * sval);
//没有实现的有
int sem_open (const char * name,int oflag,mode_t mode,unsigned int value);
int sem_close (sem_t * sem);
int sem_unlink (const char * name);
没有实现的 函数代码都是类似下面这样的,直接是返回错误:
sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
printf("本函数没有实现\n");//本人添加的 以免误用
errno = ENOSYS;
return -1;
/* sem_open */
好,下面说重点了,sem_t 就是 semaphore信号量 怎么用。
1、定义sem_t结构体
sem_t 就是一个结构体指针,定义了,是没有值的。比如
sem_t sem=NULL;
2、初始化sem_t变量
sem_init(&sem,0,0);
显然内部会分配内存,返回值为0,如果失败为非0【其实是-1,只有两种返回值,纳闷为什么不用boolean】,错误存储在errno中。
第二个参数 为0,为1 是可以在多进程中使用,但是pthread win32没有实现,所以保证永远为0;
第三个参数是初始值,如果大于0,则会发送多少个sem_post操作的。一般设置0 即可。
3、在多线程中 等待
sem_wait(&sem);
sem_timedwait(&sem,&const struct timespec *abstime));
sem_trywait(&sem);
&sem_wait是阻塞的,sem_timewait是阻塞一定时间后继续,sem_trywait是非阻塞的,非阻塞怎么用,我暂时没研究。
总之呢,wait之后,内部value就会-1;所以如果vaue小于0,那么就有线程正在等待,否则就不等待直接进行下面的工作了。
4、【重点】在主线程或其他地方 发送post,让那些工作线程逐个开始工作起来
sem_post(&sem);//让value+1
sem_post_multi(&sem,5);&//让vaue+5
5、当然就是结束了,当且仅当 sem有效 且 内部value&=0的时候,也就是没有sem_wait的时候可以销毁。
sem_destroy(&sem);
此时 sem_wait 就会失败了。所以destroy前 先 sem_post& value的绝对值 个信号 就可以了。
6、【补充】获得sem内部的value值,当且仅当==0的时候,才可以destroy,小于0 队列个数,大于0 排队数量。
sem_getvalue(&sem,&theOutValue);
以上返回值为0 正常,否则不正常。
使用这个semaphore有一个好处,比如,只有2个线程,你一下子sem_post 20次,没关系,sem_wait会执行20次的,而且是2个线程轮流。其及时对WINAPI semaphore的一个封装。
&semaphore如果在一个线程中使用,一般叫做 binary semaphore,单值。
&ps:signal.h 头文件 叫做信号 ,与这个semaphore信号量 不太一样的。
附上 临界区,互斥量,信号量,事件的区别 ,这些都属于& 线程安全的范畴,不知道还有别的没有了。
临界区,互斥量,信号量,事件的区别
===================================
四种进程或线程同步互斥的控制方法
1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。
2、互斥量:为协调共同对一个共享资源的单独访问而设计的。
3、信号量:为控制一个具有有限数量用户资源而设计。
4、事 件:用来通知线程有一些事件已发生,从而启动后继任务的开始。
临界区(Critical Section)(同一个进程内,实现互斥)
===================================
保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
互斥量(Mutex)(可以跨进程,实现互斥)
===================================
互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限,由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。
互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。
信号量(Semaphores)(主要是实现同步,可以跨进程)
===================================
信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的最大数目,不能在允许其他线程的进入,此时的信号量信号将无法发出
事件(Event)(实现同步,可以跨进程)
===================================
事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。
最后附上我自己的测试源代码:
#include &stdio.h&
#include &pthread.h&
#include &sched.h&
#include &semaphore.h&
#include &conio.h&//for getch()
#include &ctype.h&
#include&Windows.h&
#pragma comment(lib, "pthreadVC2.lib")
//必须加上这句
void*SemThreadWorker(void* Param)
printf("#1 [child %s]I am Waiting\n",Param);
//sem_wait(&sem);
//sem_timedwait(&sem,60);
//sem_trywait(&sem);
while(0==sem_wait(&sem)) {
// Wait semaphore
[child %s]I am Working in 1 second!!\n",Param);
Sleep(1000);
printf("#2 [child %s]I am Exit\n",Param);
return (void *)10;
int main()
int ret=0;
ret=sem_init(&sem,0/*int pshared process_shared*/,0/*uint init_value*/);/*SEM_VALUE_MAX == int_max*/
if(ret!=0){
printf("Semaphore
initialize failed");
exit(EXIT_FAILURE);
if(0==sem_getvalue(&sem,&ret)){printf("\n sem_getvalue value=%d \n",ret);}else{perror("@Error sem_getValue");}
//CreateThreads
pthread_t tids[5];
ret = pthread_create(&tids[0], NULL, SemThreadWorker, "1");
if (ret) {printf("Thread creation failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_create(&tids[1], NULL, SemThreadWorker, "2");
if (ret) {printf("Thread creation failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_create(&tids[2], NULL, SemThreadWorker, "3");
if (ret) {printf("Thread creation failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_create(&tids[3], NULL, SemThreadWorker, "4");
if (ret) {printf("Thread creation failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_create(&tids[4], NULL, SemThreadWorker, "5");
if (ret) {printf("Thread creation failed!!\n");exit(EXIT_FAILURE);}
Sleep(100);
printf("\n Post semaphore发送信号量过去: sem_post(&sem);\n");
//for(int i=0;i&10;i++){
sem_post(&sem);
sem_post(&sem);
Sleep(100);
if(sem_post(&sem)!=0){
printf("Error sem_post ");
if(0==sem_getvalue(&sem,&ret)){printf("\n sem_getvalue value=%d \n",ret);}else{perror("@Error sem_getValue");}
if(sem_post(&sem)!=0){
printf("Error sem_post ");
if(0==sem_getvalue(&sem,&ret)){printf("\n sem_getvalue value=%d \n",ret);}else{perror("@Error sem_getValue");}
if(sem_post_multiple(&sem,5)!=0){
printf("Error sem_post_multiple ");
if(0==sem_getvalue(&sem,&ret)){printf("\n sem_getvalue value=%d \n",ret);}else{perror("@Error sem_getValue");}
Sleep(2000);
printf("\n sem_getvalue(&sem,&ret);\n");
//sem_open
//sem_close(&sem);
//sem_unlink
if(0==sem_getvalue(&sem,&ret)){printf("\n sem_getvalue value=%d \n",ret);}else{perror("@Error sem_getValue");}
//为了让sem_wait全部停止阻塞,才可以destroy
sem_post_multiple(&sem,-ret);
printf("\n sem_destroy(&sem);\n\n");
//第一次 sem_destroy return 0
if(sem_destroy(&sem)!=0){
perror("@Error sem_destroy ");
//第二次 sem_destroy 多次 return -1
if(sem_destroy(&sem)!=0){
perror("@Error sem_destroy ");
if(sem_post(&sem)!=0){
printf("@Error sem_post \n");
printf(" Wait for thread pthread_join synchronization...\n");
void *threadResult=NULL;
ret = pthread_join(tids[0], &threadResult);
if (ret){printf("Thread join failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_join(tids[1], &threadResult);
if (ret){printf("Thread join failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_join(tids[2], &threadResult);
if (ret){printf("Thread join failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_join(tids[3], &threadResult);
if (ret){printf("Thread join failed!!\n");exit(EXIT_FAILURE);}
ret = pthread_join(tids[4], &threadResult);
if (ret){printf("Thread join failed!!\n");exit(EXIT_FAILURE);}
printf("press any key to continue...\n");
//getchar();
五个线程工作,用semaphore来管理队列
阅读(...) 评论()

我要回帖

更多关于 spinlock和mutex 的文章

 

随机推荐