您的位置:首页 > 其它

使用信号量进行线程间同步

2009-06-09 15:39 288 查看
转载地址http://hellobmw.com/archives/semaphore-examples-for-windows-and-unix.html

Windows 平台信号量(Semaphore)

#include <stdio.h>
#include <Windows.h>
#define MAX_SEM_COUNT 10
#define THREADCOUNT 12
HANDLE ghSemaphore;
DWORD WINAPI ThreadProc( LPVOID );
void main(int argc, char* argv[])
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(
NULL,           // default security attributes - lpSemaphoreAttributes是信号量的安全属性
MAX_SEM_COUNT,  // initial count - lInitialCount是初始化的信号量
MAX_SEM_COUNT,  // maximum count - lMaximumCount是允许信号量增加到最大值
NULL);          // unnamed semaphore - lpName是信号量的名称
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d/n", GetLastError());
return;
}
// Create worker threads
for( i=0; i <THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL,       // default security attributes
0,          // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL,       // no thread function arguments
0,          // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d/n", GetLastError());
return;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and semaphore handles
for( i=0; i <THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore,   // handle to semaphore
0L);           // zero-second time-out interval
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded/n", GetCurrentThreadId());

// Ensure a thread performs only once
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore,  // handle to semaphore - hSemaphore是要增加的信号量句柄
1,            // increase count by one - lReleaseCount是增加的计数
NULL) )       // not interested in previous count - lpPreviousCount是增加前的数值返回
{
printf("ReleaseSemaphore error: %d/n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out/n", GetCurrentThreadId());
break;
}
}
return TRUE;
}


Unix 平台信号量(Semaphore)

/* semabinit.c - initialize a semaphore for use by programs sema and semb */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
/* The semaphore key is an arbitrary long integer which serves as an
external identifier by which the semaphore is known to any program
that wishes to use it. */
#define KEY (1492)
void main()
{
int id; /* Number by which the semaphore is known within a program */
/* The next thing is an argument to the semctl() function. Semctl()
does various things to the semaphore depending on which arguments
are passed. We will use it to make sure that the value of the
semaphore is initially 0. */
union semun {
int val;
struct semid_ds *buf;
ushort * array;
} argument;
argument.val = 0;
/* Create the semaphore with external key KEY if it doesn't already
exists. Give permissions to the world. */
id = semget(KEY, 1, 0666 | IPC_CREAT);
/* Always check system returns. */
if(id <0)
{
fprintf(stderr, "Unable to obtain semaphore. ");
exit(0);
}
/* What we actually get is an array of semaphores. The second
argument to semget() was the array dimension - in our case
1. */
/* Set the value of the number 0 semaphore in semaphore array
# id to the value 0. */
if( semctl(id, 0, SETVAL, argument) <0)
{
fprintf( stderr, "Cannot set semaphore value. ");
}
else
{
fprintf(stderr, "Semaphore %d initialized. ", KEY);
}
}


/* Semaphore example program a (sema.c) */
/* We have two programs, sema and semb. Semb may be initiated at any
time, but will be forced to wait until sema is executed. Sema and
semb do not have to be executed by the same user! */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define KEY (1492)
/* This is the external name by which the semaphore is known to any
program that wishes to Access it. */
void main()
{
int id; /* Internal identifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to perform on the semaphore. */
int retval; /* Return value from semop() */
/* Get the index for the semaphore with external name KEY. */
id = semget(KEY, 1, 0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Program sema cannot find semaphore, exiting. ");
exit(0);
}
/* Do a semaphore V-operation. */
printf("Program sema about to do a V-operation. ");
/* Set up the sembuf structure. */
/* Which semaphore in the semaphore array : */
operations[0].sem_num = 0;
/* Which operation? Add 1 to semaphore value : */
operations[0].sem_op = 1;
/* Set the flag so we will wait : */
operations[0].sem_flg = 0;
/* So do the operation! */
retval = semop(id, operations, 1);
if(retval == 0)
{
printf("Successful V-operation by program sema. ");
}
else
{
printf("sema: V-operation did not succeed. ");
perror("REASON");
}
}
/* Think carefully about what the V-operation does. If sema is executed
twice, then semb can execute twice. */


/* Semaphore example program b (semb.c) */
/* We have two programs, sema and semb. Semb may be initiated at any
time, but will be forced to wait until sema is executed. Sema and
semb do not have to be executed by the same user! */
/* HOW TO TEST:
Execute semb &
The & is important - otherwise you would have have to move to
a different terminal to execute sema.
Then execute sema.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#define KEY (1492)
/* This is the external name by which the semaphore is known to any
program that wishes to access it. */
void main()
{
int id; /* Internal identifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to perform on the semaphore. */
int retval; /* Return value from semop() */
/* Get the index for the semaphore with external name KEY. */
id = semget(KEY, 1, 0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Program semb cannot find semaphore, exiting. ");
exit(0);
}
/* Do a semaphore P-operation. */
printf("Program semb about to do a P-operation. ");
printf("Process id is %d ", getpid());
/* Set up the sembuf structure. */
/* Which semaphore in the semaphore array : */
operations[0].sem_num = 0;
/* Which operation? Subtract 1 from semaphore value : */
operations[0].sem_op = -1;
/* Set the flag so we will wait : */
operations[0].sem_flg = 0;
/* So do the operation! */
retval = semop(id, operations, 1);
if(retval == 0)
{
printf("Successful P-operation by program semb. ");
printf("Process id is %d ", getpid());
}
else
{
printf("semb: P-operation did not succeed. ");
}
}
/* Think carefully about what the V-operation does. If sema is executed
twice, then semb can execute twice. */
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: