Windows/Unix 信号量(Semaphore)示例程序

Windows/Unix 信号量(Semaphore)示例程序

至于什么是信号量(Semaphore),网上相关资料多得很,一搜一大把,我就不做重复劳动了。只是把关于使用信号量的示例程序贴一下当作笔记,万一能对大家有点点帮助那就更好了。Windows 平台的代码来源于 MSDN,Unix 平台的代码是 Google 来的。

Part 1 - 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 semaphorewith initial and max counts of MAX_SEM_COUNT

    ghSemaphore = CreateSemaphore(
        NULL,          // default securityattributes - lpSemaphoreAttributes是信号量的安全属性
        MAX_SEM_COUNT,  //initial count - lInitialCount是初始化的信号量
        MAX_SEM_COUNT,  //maximum count - lMaximumCount是允许信号量增加到最大值
        NULL);          // unnamed semaphore - lpName是信号量的名称

    if (ghSemaphore == NULL)
    {
        printf("CreateSemaphoreerror: %d\n", GetLastError());
        return;
    }

    // Create workerthreads

    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("CreateThreaderror: %d\n", GetLastError());
            return;
        }
    }

    // Wait for allthreads to terminate

    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE,INFINITE);

    // Close thread andsemaphore 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 thesemaphore gate.
        dwWaitResult = WaitForSingleObject(
            ghSemaphore,   // handle to semaphore
            0L);          // zero-second time-outinterval

        switch(dwWaitResult)
        {
            // Thesemaphore object was signaled.
        case WAIT_OBJECT_0:
            // TODO:Perform task
            printf("Thread %d: waitsucceeded\n", GetCurrentThreadId());
           
            // Ensure athread 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: waittimed out\n", GetCurrentThreadId());
            break;
        }
    }
    return TRUE;
}

Part 2 - Unix 平台信号量(Semaphore)示例程序

 

/* semabinit.c - initialize a semaphore for use byprograms sema and semb */

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>

/* The semaphore key is an arbitrarylong 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 bywhich the semaphore is known within a program */

/* The next thing is an argument tothe 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 externalkey 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 toobtain semaphore. ");
exit(0);
}

/* What we actually get is an array ofsemaphores. The second
argument to semget() was the array dimension - in our case
1. */

/* Set the value of the number 0semaphore in semaphore array
# id to the value 0. */

if( semctl(id,0, SETVAL, argument)<0)
{
fprintf( stderr, "Cannot setsemaphore value. ");
}
else
{
fprintf(stderr, "Semaphore%d initialized. ", KEY);
}

/* Semaphore example program a (sema.c) */
/* We have two programs, sema and semb. Semb may beinitiated 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 semaphoreis known to any
program that wishes to Access it. */

void main()
{
int id; /* Internalidentifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to performon the semaphore. */

int retval; /* Return value from semop() */

/* Get the index for the semaphorewith external name KEY. */
id = semget(KEY, 1,0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Programsema 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 theV-operation does. If sema is executed
twice, then semb can execute twice. */

/* Semaphore exampleprogram b (semb.c) */
/* We have two programs, sema and semb. Semb may beinitiated 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 semaphoreis known to any
program that wishes to access it. */

void main()
{
int id; /* Internalidentifier of the semaphore. */
struct sembuf operations[1];
/* An "array" of one operation to performon the semaphore. */

int retval; /* Return value from semop() */

/* Get the index for the semaphorewith external name KEY. */
id = semget(KEY, 1,0666);
if(id <0)
/* Semaphore does not exist. */
{
fprintf(stderr, "Programsemb 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 theV-operation does. If sema is executed
twice, then semb can execute twice. */

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Java信号量使用示例程序: ```java import java.util.concurrent.Semaphore; public class SemaphoreExample { public static void main(String[] args) { Semaphore semaphore = new Semaphore(3); // 创建一个信号量,初始值为3 // 创建5个线程 for (int i = 1; i <= 5; i++) { Thread thread = new Thread(new Worker(semaphore, i)); thread.start(); } } static class Worker implements Runnable { private final Semaphore semaphore; private final int id; public Worker(Semaphore semaphore, int id) { this.semaphore = semaphore; this.id = id; } @Override public void run() { try { semaphore.acquire(); // 等待信号量,如果信号量为0则阻塞 System.out.println("Worker " + id + " acquired semaphore"); Thread.sleep(1000); // 模拟工作 } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); // 释放信号量 System.out.println("Worker " + id + " released semaphore"); } } } } ``` 在这个示例程序中,创建了一个初始值为3的信号量。然后创建了5个线程,每个线程都是一个Worker实例,Worker实例的构造函数中传入了信号量和线程ID。每个线程运行时,首先尝试获取信号量,如果信号量为0,则阻塞等待。如果成功获取信号量,就输出一个日志,然后模拟一秒钟的工作时间。最后释放信号量并输出一个日志。 由于信号量的初始值为3,所以前3个线程可以同时获取信号量并运行,后面的两个线程需要等待前面的线程释放信号量后才能获取。输出结果如下: ``` Worker 1 acquired semaphore Worker 2 acquired semaphore Worker 3 acquired semaphore Worker 1 released semaphore Worker 4 acquired semaphore Worker 2 released semaphore Worker 5 acquired semaphore Worker 3 released semaphore Worker 4 released semaphore Worker 5 released semaphore ``` 可以看到,前三个线程可以同时获取信号量,后面的两个线程需要等待前面的线程释放信号量后才能获取。这就是信号量的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值