sem_wait函数也是一个原子操作,它的作用是从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法。也就是说,如果你对一个值为2的信号量调用sem_wait(),线程将会继续执行,将信号量的值将减到1。如果对一个值为0的信号量调用sem_wait(),这个函数就会原地等待直到有其它线程增加了这个值使它不再是0为止。如果有两个线程都在sem_wait()中等待同一个信号量变成非零值,那么当它被第三个线程增加 一个“1”时,等待线程中只有一个能够对信号量做减法并继续执行,另一个还将处于等待状态。sem_trywait(sem_t *sem)是函数sem_wait的非阻塞版,它直接将信号量sem减1,同时返回错误代码。
sem_wait() 减小(锁定)由sem指定的信号量的值.如果信号量的值比0大,那么进行减一的操作,函数立即返回.如果信号量当前为0值,那么调用就会一直阻塞直到或者是信号量变得可以进行减一的操作(例如,信号量的值比0大),或者是信号处理程序中断调用
sem_trywait() 和 sem_wait()是一样的,除了如果不能够对信号量立即进行减一,那么sem_trywait()就会返回一个错误(错误号是AGAIN)而不是锁定.sem_timedwait() 和 sem_wait()是一样的,除了如果减一操作不能立即执行的话,abs_timeout 指定了调用应该被阻塞的时间限制.abs_timeout 参数指向了一个结构体指定了由秒和纳秒组成的绝对的超时值:从1970-01-01 00:00:00 +0000纪元开始的UTC,结构体的定义如下:struct timespec {time_t tv_sec/* Seconds */long tv_nsec/* Nanoseconds [0 .. 999999999] */}如果超时值已经超过了调用规定的值,那么信号量不能被立即锁定,之后sem_timedwait() 为超时失败(error设置为ETIMEDOUT).
如果操作立即生效,那么sem_timedwait() 永远不会返回超时的错误,不管abs_timeout的值.更进一步的是,在这种情况下abs_timeout值的有效性都不会检查. EINTR The call was interrupted by a signal handlersee signal(7).//调用被信号处理中断
EINVAL sem is not a valid semaphore.//sem不是有效的信号量
The following additional error can occur for sem_trywait()://下面的错误是sem_trywait()可能发生的:
EAGAIN The operation could not be performed without blocking (i.e., thesemaphore currently has the value zero).//除了锁定无法进行别的操作(如信号量当前是0值).
The following additional errors can occur for sem_timedwait()://下面的错误是sem_timedwait()可能发生的:
EINVAL The value of abs_timeout.tv_nsecs is less than 0, or greater than orequal to 1000 million.//abs_timeout.tv_nsecs 的值比0小或者大于等于1000毫秒(译者注:纳秒的值不能比0小,不能比1秒大)
ETIMEDOUTThe call timed out before the semaphore could be locked.//在信号量锁定之前就超时了 对这些函数,信号处理程序总是会中断阻塞,不管是否使用了sigaction(2)的SA_RESTART标志位.
#include<iostream>
#include <Windows.h>
using namespace std
const int MAX_SEM_COUNT = 5//信号量数量
const int THREAD_COUNT = 10//线程数量
HANDLE g_sem//全局信号量对象句柄
DWORD WINAPI threadFunc(LPVOID)//线程函数前向声明
int main()
{
HANDLE arrThread[THREAD_COUNT]
g_sem = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL)
if (!g_sem)
{
cout<<"call CreateSemaphore() failed!"<<endl
return -1
}
DWORD threadID = -1
for (int i = 0i <THREAD_COUNT++i)
{
arrThread[i] = CreateThread(NULL, 0, threadFunc, NULL, 0, &threadID)
if (!arrThread[i])
{
cout<<"call CreateThread() failed!"<<endl
return -2
}
}
WaitForMultipleObjects(THREAD_COUNT, arrThread, true, INFINITE)
for (int i = 0i <THREAD_COUNT++i)
{
CloseHandle(arrThread[i])
}
CloseHandle(g_sem)
system("pause")
return 0
}
//线程函数,使用信号量的例子
DWORD WINAPI threadFunc(LPVOID)
{
DWORD waitResult
bool bContinue = true
while (bContinue)
{
waitResult = WaitForSingleObject(g_sem,0)
switch (waitResult)
{
case WAIT_OBJECT_0:
cout <<GetCurrentThreadId()<<" wait sem succeed!"<<endl
bContinue = false
Sleep(5)
if (!ReleaseSemaphore(g_sem, 1, NULL))
{
cout<<"call ReleaseSemaphore() failed!"<<endl
return GetLastError()
}
break
case WAIT_TIMEOUT:
cout <<GetCurrentThreadId()<<" wait sem timeout!"<<endl
break
}
}
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)