线程之间的信号量 Semaphore

同一个进程中不同线程之间的同步可以使用 POSIX Semaphores(其定义在semaphore.h),这个信号量要比进程间通信使用的信号量的结构简单,注意两者是不同的事物。

创建信号量对象: sem_t sem_name;
很简单的一个变量,其中的sem_t类型也非常简单,下面是其类型定义:
typedef volatile unsigned char atomic_t
typedef atomic_t sem_t

初始化信号量:
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数一:是指向信号量对象的指针
参数二:表明该信号量是否在父子进程之间共享(Linux目前是不支持的)
参数三:要信号量设定的初始值。

查询信号量:
int sem_getvalue(sem_t *sem, int *valp);
查询当前信号量的值,其值会以参数的形式返回到valp上。

P操作,索取信号量:
int sem_wait(sem_t *sem);
参数是:是指向信号量的指针。
若信号量的值为0,则线程阻塞。否则信号量的值-1。

V操作,释放信号量:
int sem_post(sem_t *sem);
参数:是指向信号量的指针。
信号量的值会+1,并且会唤醒某一个阻塞中的线程。

删除信号量:
int sem_destroy(sem_t *sem);
参数:是指向信号量的指针。
注意删除信号量时不应该存在阻塞在该信号量上的线程,否则无法删除。

上面说的主要是针对Linux,而在Mac OSX下,并不支持sem_init()对信号量的建立,而是用sem_open()。

下面的测试程序(运行在Mac OSX)中,注释部分是适用于linux的。
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#define NITER 1000000
int count = 0; //两个线程共享同一个资源:count
sem_t sem_for_linux;
sem_t *s;

void * ThreadAdd(void * a)
{
    int i, tmp;
   
    for(i = 0; i < NITER; i++)
    {
        sem_wait(s);
        //sem_wait(&sem_for_linux);
        //++count; //把自增的过程放大给你看
        tmp = count;      /* copy the global count locally */
        tmp = tmp+1;      /* increment the local copy */
        count = tmp;      /* store the local value into the global count */
        sem_post(s);
        //sem_post(&sem_for_linux);
    }
        return NULL;
}

int main(int argc, char * argv[])
{
    pthread_t tid1, tid2;

    sem_unlink("s");
    s = sem_open("s", O_CREAT, 0, 1);;
    //sem_init(&sem_for_linux, 0, 1);
   
   
    // 创建两个线程
    if(pthread_create(&tid1, NULL, ThreadAdd, NULL))
    {
        printf("\n ERROR creating thread 1");
        exit(1);
    }
   
    if(pthread_create(&tid2, NULL, ThreadAdd, NULL))
    {
        printf("\n ERROR creating thread 2");
        exit(1);
    }
   
    // 等待两个线程都结束
    if(pthread_join(tid1, NULL))     /* wait for the thread 1 to finish */
    {
        printf("\n ERROR joining thread");
        exit(1);
    }
   
    if(pthread_join(tid2, NULL))        /* wait for the thread 2 to finish */
    {
        printf("\n ERROR joining thread");
        exit(1);
    }
   
    if (count < 2 * NITER)
        printf("\n BOOM! count is [%d], should be %d\n", count, 2*NITER);
    else
        printf("\n OK! count is [%d]\n", count);
   
    //sem_destroy(&sem_for_liux);
    sem_destroy(s);
   
    pthread_exit(NULL);
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用Semaphore实现两线程同步的C++代码: ```c++ #include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <semaphore.h> using namespace std; sem_t sem; void thread1() { cout << "Thread 1 is running." << endl; sem_post(&sem); // 发送信号 } void thread2() { sem_wait(&sem); // 等待信号 cout << "Thread 2 is running." << endl; } int main() { sem_init(&sem, 0, 0); // 初始化信号 thread t1(thread1); thread t2(thread2); t1.join(); t2.join(); sem_destroy(&sem); // 销毁信号 return 0; } ``` 这个例子中,我们使用了`sem_t`和`sem_init()`、`sem_wait()`、`sem_post()`、`sem_destroy()`四个函数来实现Semaphore。`sem_t`是一个结构体类型,用于存储Semaphore的信息。`sem_init()`函数用于初始化Semaphore,第一个参数是Semaphore结构体指针,第二个参数是0表示这个Semaphore是用于线程间同步的,第三个参数是Semaphore的初值,这里设为0。`sem_wait()`函数用于等待Semaphore信号,如果Semaphore的值为0,则该函数阻塞线程,直到Semaphore的值大于0;如果Semaphore的值大于0,则该函数将Semaphore的值减1,然后线程继续执行。`sem_post()`函数用于发送Semaphore信号,将Semaphore的值加1,表示Semaphore可以被下一个等待的线程使用。`sem_destroy()`函数用于销毁Semaphore。 在这个例子中,我们创建了两个线程,线程1通过调用`sem_post()`函数发送Semaphore信号线程2通过调用`sem_wait()`函数等待Semaphore信号。由于Semaphore的初值为0,线程2会在等待Semaphore信号时被阻塞,直到线程1发送了Semaphore信号。这样就实现了两个线程的同步。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值