(11) linux 上的用于线程进程同步的信号量 semaphore,函 sem_init()、sem_destroy()、sem_wait()、sem_post()、

(1)先给出一言的教导

在这里插入图片描述
在这里插入图片描述

(2)信号量属于 linux 内核里的知识。缺乏源代码的支撑,所以比较难以理解。以下给出网上的大师们的讲解的源代码

在这里插入图片描述

++解析

wait(S)、signal(S) 也可以记为P(S)、V(S),这对原语可用于实现系统资源的“申请”和“释放”。

S.value 的初值表示系统中某种资源的数目

对信号量 S的一次 P操作意味着进程请求一个单位的该类资源,因此需要执行 S.value–, 表示资源数减 1,当 S.value<0时表示该类资源已分配完毕,因此进程应调用 block原语进行自我阻塞(当前运行的进程从运行态阻塞态),主动放弃处理机,并插入该类资源的等待队列 S.L中。可见,该机制遵循了“让权等待”原则,不会出现“忙等”现象

对信号量 S的一次 V操作意味着进程释放一个单位的该类资源,因此需要执行 S.value++,表示资源数加 1,若加 1后仍是 S.value<= 0,表示依然有进程在等待该类资源,因此应调 用wakeup原语唤醒等待队列中的第一个进程(被唤醒进程从阻塞态>就绪态)

前一个进程释放一个资源就唤醒一个新的进程进行使用。

(3)介绍介绍关于信号量的重要函数的定义与使用, sem_init()

在这里插入图片描述

++代码举例:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define  NUM_THREADS  2

sem_t semaphore;                 // 信号量保护下面的全局变量
int shared_resource = 0;

void* thread_func(void* arg) 
{
    int thread_num = *(int*)arg; // 计算形参的值
    
    sem_wait(&semaphore);        // 等待信号量
    
    printf("Thread %d: Accessing shared resource (value: %d)\n", thread_num, shared_resource);
    shared_resource++;    // 访问共享资源
    sleep(1);             // 模拟处理时间
    printf("Thread %d: Done with shared resource (new value: %d)\n", thread_num, shared_resource);
    
    sem_post(&semaphore); // 释放信号量
    
    return NULL;
}

int main() 
{
    pthread_t  threads[NUM_THREADS]; // 创建两个子线程
    int thread_args[NUM_THREADS];
    
    if (sem_init( &semaphore, 0, 1 ) != 0) { // 初始化信号量,只有 1 个共享资源,用于线程间同步
        perror("sem_init");        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < NUM_THREADS; i++)    // 创建线程
    { 
        thread_args[i] = i + 1;              // 设置线程函数里的参数
        if ( pthread_create( &threads[i], NULL, thread_func, &thread_args[i]) != 0 ) {
            perror("pthread_create");     exit( EXIT_FAILURE );
        }
    }

    for (int i = 0; i < NUM_THREADS; i++)  // 等待所有线程完成
        pthread_join(threads[i], NULL);

    sem_destroy(&semaphore);  // 销毁信号量

    return 0;
}

++ 上面的例子代码中:在这个示例中,我们创建了两个线程,它们通过信号量来同步对共享资源的访问。信号量的初始值为 1,这意味着一次只能有一个线程访问共享资源。sem_wait 函数用于等待信号量,而 sem_post 函数用于释放信号量。

(4)函数 sem_destroy()

在这里插入图片描述

(5)函数 sem_wait()

在这里插入图片描述

(6)函数 sem_post ()

在这里插入图片描述

++ 以下是一个使用 sem_post 和 sem_wait 的简单示例,展示了如何在生产者-消费者模型中同步对缓冲区的访问。创建了一个生产者线程和一个消费者线程,它们通过信号量和互斥锁来同步对共享缓冲区的访问:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE]; // 可以存储 10 个数据
int count = 0;           // 缓冲区中当前存储的项数
pthread_mutex_t mutex ;  // 保护对缓冲区和计数的访问的互斥锁

sem_t empty ;            // 表示缓冲区中空位的信号量
sem_t full  ;            // 表示缓冲区中已占用位的信号量

void* producer(void* arg) 
{
    for (int i = 0; i < 20; i++)    // 生产20个项
    { 
        int item = rand() % 100 ;   // 生成一个随机项
        
        sem_wait( &empty );         // 等待缓冲区中有空位。先拿到空信号量
        
        pthread_mutex_lock(&mutex); // 锁定缓冲区
        buffer[count] = item;       // 将项放入缓冲区
        count++;
        printf("Produced: %d\n", item);
        pthread_mutex_unlock(&mutex); // 解锁缓冲区
        
        sem_post(&full);              // 增加表示已占用位的信号量,发布一次满信号量
        
        sleep(rand() % 2);            // 模拟生产时间
    }
    return NULL;
}

void* consumer(void* arg) 
{
    for (int i = 0; i < 20; i++)    // 消费20个项
    { 
        sem_wait( &full );          // 等待缓冲区中有已占用位,先拿到满信号量,表示有数据可消费
        
        pthread_mutex_lock(&mutex) ;   // 锁定缓冲区
        int item = buffer[count - 1] ; // 从缓冲区中取出项
        count--;
        printf("Consumed: %d\n", item) ;
        pthread_mutex_unlock(&mutex) ; // 解锁缓冲区
        
        sem_post( &empty );  // 增加表示空位的信号量,发布一次空信号量
        
        sleep( rand() % 2 ); // 模拟消费时间
    }
    return NULL;
}

int main() 
{
    pthread_t  prod_thread, cons_thread ; // 要创建两个线程
    
    sem_init( &empty, 0, BUFFER_SIZE );   // 标识初始的时的资源数量为 10
    sem_init( &full , 0, 0 );             // 标识初始的时的资源数量为  0
    									   // 所以即使消费线程先运行也要陷入睡眠
    pthread_mutex_init( &mutex, NULL) ;   // 初始化互斥锁
    
    pthread_create( &prod_thread, NULL, producer, NULL) ;   // 创建生产者和消费者线程
    pthread_create( &cons_thread, NULL, consumer, NULL) ;
    pthread_join( prod_thread, NULL ) ;   // 等待线程完成
    pthread_join( cons_thread, NULL ) ;
    
    sem_destroy( &empty ) ;  // 销毁信号量和互斥锁
    sem_destroy( &full  ) ;
    pthread_mutex_destroy( &mutex );
    
    return 0;
}

++ 给出上面例子的解释

在这里插入图片描述

(7)

谢谢

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhangzhangkeji

谢谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值