你走了以后我的心好凉凉………………………

&&/&&&&/&&&&/&&
信号量机构是一种功能较强的机制,可用来解决互斥与同步的问题,它只能被两个标准的原语wait(S)和signal(S)来访问,也可以记为&P操作&和&V操作&。
原语是指完成某种功能且不被分割不被中断执行的操作序列,通常可由硬件来实现完成不被分割执行特性的功能。如前述的&Test-and-Set&和&Swap&指令,就是由硬件实现的原子操作。原语功能的不被中断执行特性在单处理机时可由软件通过屏蔽中断方法实现。
原语之所以不能被中断执行,是因为原语对变量的操作过程如果被打断,可能会去运行另一个对同一变量的操作过程,从而出现临界段问题。如果能够找到一种解决临界段问题的元方法,就可以实现对共享变量操作的原子性。
整型信号量
整型信号量被定义为一个用于表示资源数目的整型量S,wait和signal操作可描述为:
while (S&=0);
signal(S){
wait操作中,只要信号量S&=0,就会不断地测试。因此,该机制并未遵循&让权等待& 的准则,而是使进程处于&忙等&的状态。
记录型信号量
记录型信号量是不存在&忙等&现象的进程同步机制。除了需要一个用于代表资源数目的整型变量value外,再增加一个进程链表L,用于链接所有等待该资源的进程,记录型信号量是由于用了记录型的数据结构得名。记录型信号量可描述为:
typedef struct{
struct process *L;
相应的wait(S)和signal(S)的操作如下:
void wait (semaphore S) { //相当于申请资源
S.value--;
if(S.value&0) {
add this process to S.L;
block(S.L);
wait操作,S.value--,表示进程请求一个该类资源,当S.value&0时,表示该类资源已分配完毕,因此进程应调用block原语,进行自我阻塞,放弃处理机,并插入到该类资源的等待队列S.L中,可见该机制遵循了&让权等待&的准则。
void signal (semaphore S) {
//相当于释放资源
S.value++;
if(S.value&=0){
remove a process P from S.L;
wakeup(P);
signal操作,表示进程释放一个资源,使系统中可供分配的该类资源数增1,故S.value++。若加1后仍是S.value&=0,则表示在S.L中仍有等待该资源的进程被阻塞,故还应调用wakeup 原语,将S.L中的第一个等待进程唤醒。
利用信号量实现同步
信号量机构能用于解决进程间各种同步问题。设S为实现进程P1、P2同步的公共信号量,初值为0。进程P2中的语句y要使用进程P1中语句x的运行结果,所以只有当语句x执行完成之后语句y才可以执行。其实现进程同步的算法如下:
semaphore S = 0;
//初始化信号量
//告诉进程P2,语句V已经完成
//检查语句x是否运行完成
// 检查无误,运行y语句
利用信号量实现进程互斥
信号量机构也能很方便地解决进程互斥问题。设S为实现进程Pl、P2互斥的信号量,由于每次只允许一个进程进入临界区,所以S的初值应为1(即可用资源数为1)。只需把临界区置于P(S)和V(S)之间,即可实现两进程对临界资源的互斥访问。其算法如下:
semaphore S = 1;
//初化信号量
// 准备开始访问临界资源,加锁
// 进程P1的临界区
// 访问结束,解锁
P(S); //准备开始访问临界资源,加锁
// 进程P2的临界区;
// 访问结束,解锁
互斥的实现是不同进程对同一信号量进行P、V操作,一个进程在成功地对信号量执行了 P操作后进入临界区,并在退出临界区后,由该进程本身对该信号量执行V操作,表示当前没有进程进入临界区,可以让其他进程进入。
利用信号量实现前驱关系
信号量也可以用来描述程序之间或者语句之间的前驱关系。图2-8给出了一个前驱图,其中S1, S2, S3, &, S6是最简单的程序段(只有一条语句)。为使各程序段能正确执行,应设置若干个初始值为&0&的信号量。例如,为保证S1 -& S2、 S1 -& S3的前驱关系,应分别设置信号量a1、a2。同样,为了保证 S2 -& S4、S2 -&S5、S3 -& S6、S4 -& S6、S5 -& S6,应设置信号量bl、b2、c、d、e。&
图2-8 前驱图举例
实现算法如下:
al=a2=bl=b2=c=d=e=0;
//初始化信号量
//S1已经运行完成
//检查S1是否运行完成
V(bl); V(b2); // S2已经运行完成
//检查S1是否已经运行完成
//S3已经运行完成
//检查S2是否已经运行完成
//S4已经运行完成
//检查S2是否已经运行完成
// S5已经运行完成
//检查S3是否已经运行完成
//检查S4是否已经运行完成
//检查S5是否已经运行完成
分析进程同步和互斥问题的方法步骤
1) 关系分析。找出问题中的进程数,并且分析它们之间的同步和互斥关系。同步、互斥、前驱关系直接按照上面例子中的经典范式改写。
2) 整理思路。找出解决问题的关键点,并且根据做过的题目找出解决的思路。根据进程的操作流程确定P操作、V操作的大致顺序。
3) 设置信号量。根据上面两步,设置需要的信号量,确定初值,完善整理。利用信号量实现前趋关系_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
利用信号量实现前趋关系
上传于||暂无简介
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
你可能喜欢Linux之信号量,比较全面,个人总结。_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Linux之信号量,比较全面,个人总结。
上传于||暂无简介
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
下载文档到电脑,查找使用更方便
还剩15页未读,继续阅读
你可能喜欢69385人阅读
Windows多线程(14)
Windows编程(86)
阅读本篇之前推荐阅读以下姊妹篇:《》《》《》《》&前面介绍了、、在经典线程同步问题中的使用。本篇介绍用信号量来解决这个问题。首先也来看看如何使用信号量,信号量常用有三个函数,使用很方便。下面是这几个函数的原型和使用说明。第一个函数功能:创建信号量函数原型:CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,LONG lInitialCount,LONG lMaximumCount,LPCTSTR lpName 函数说明:第一个参数表示安全控制,一般直接传入。第二个参数表示初始资源数量。第三个参数表示最大并发数量。第四个参数表示信号量的名称,传入表示匿名信号量。&第二个 函数功能:打开信号量函数原型:OpenSemaphore(DWORD dwDesiredAccess,BOOL bInheritHandle,LPCTSTR lpName函数说明:第一个参数表示访问权限,对一般传入。详细解释可以查看文档。第二个参数表示信号量句柄继承性,一般传入即可。第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个信号量。&第三个 函数功能:递增信号量的当前资源计数函数原型:ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount,&&LPLONG lpPreviousCount&函数说明:第一个参数是信号量的句柄。第二个参数表示增加个数,必须大于且不超过最大资源数量。第三个参数可以用来传出先前的资源计数,设为表示不需要传出。&注意:当前资源数量大于0,表示信号量处于触发,等于0表示资源已经耗尽故信号量处于末触发。在对信号量调用等待函数时,等待函数会检查信号量的当前资源计数,如果大于0(即信号量处于触发状态),减1后返回让调用线程继续执行。一个线程可以多次调用等待函数来减小信号量。&&最后一个 信号量的清理与销毁由于信号量是内核对象,因此使用()就可以完成清理与销毁了。&在经典多线程问题中设置一个信号量和一个关键段。用信号量处理主线程与子线程的同步,用关键段来处理各子线程间的互斥。详见代码:#include &stdio.h&
#include &process.h&
#include &windows.h&
unsigned int __stdcall Fun(void *pPM);
const int THREAD_NUM = 10;
//信号量与关键段
g_hThreadP
CRITICAL_SECTION
g_csThreadC
int main()
经典线程同步 信号量Semaphore\n&);
printf(& -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n&);
//初始化信号量和关键段
g_hThreadParameter = CreateSemaphore(NULL, 0, 1, NULL);//当前0个资源,最大允许1个同时访问
InitializeCriticalSection(&g_csThreadCode);
handle[THREAD_NUM];
g_nNum = 0;
int i = 0;
while (i & THREAD_NUM)
handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
WaitForSingleObject(g_hThreadParameter, INFINITE);//等待信号量&0
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
//销毁信号量和关键段
DeleteCriticalSection(&g_csThreadCode);
CloseHandle(g_hThreadParameter);
for (i = 0; i & THREAD_NUM; i++)
CloseHandle(handle[i]);
unsigned int __stdcall Fun(void *pPM)
int nThreadNum = *(int *)pPM;
ReleaseSemaphore(g_hThreadParameter, 1, NULL);//信号量++
Sleep(50);//some work should to do
EnterCriticalSection(&g_csThreadCode);
Sleep(0);//some work should to do
printf(&线程编号为%d
全局资源值为%d\n&, nThreadNum, g_nNum);
LeaveCriticalSection(&g_csThreadCode);
}运行结果如下图:可以看出来,信号量也可以解决线程之间的同步问题。&由于信号量可以计算资源当前剩余量并根据当前剩余量与零比较来决定信号量是处于触发状态或是未触发状态,因此信号量的应用范围相当广泛。本系列的《秒杀多线程第十篇 生产者消费者问题》将再次使用它来解决线程同步问题,欢迎大家参阅。&至此,经典线程同步问题全部结束了,下一篇《》将会对其作个总结以梳理各知识点。转载请标明出处,原文地址:如果觉得本文对您有帮助,请点击顶支持一下,您的支持是我写作最大的动力,谢谢。&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5063306次
积分:32921
积分:32921
排名:第97名
原创:156篇
评论:4632条
文章:17篇
阅读:1293494
文章:15篇
阅读:1035894
文章:130篇
阅读:4688276
文章:11篇
阅读:379736您的举报已经提交成功,我们将尽快处理,谢谢!
上BAIDU, google搜就是了
大家还关注
(window.slotbydup=window.slotbydup || []).push({
id: '2081942',
container: s,
size: '1000,60',
display: 'inlay-fix'

我要回帖

更多关于 好心高凉人 的文章

 

随机推荐