【LeetCode1114】按序打印(多线程,信号量)

简介: 第一次在leetcode上做这种多线程题目,对于这种“同步”问题,需要明白线程在哪里需要阻塞(对应PV操作中的P),再找对应的V部分(释放资源)。并且题目这里不要求考察临界资源的访问(互斥关系),只需要考虑同步关系。先想的printB之前需要阻塞,因为需要等A完成打印,所

一、题目

image.pngimage.png



二、思路

第一次在leetcode上做这种多线程题目,对于这种“同步”问题,需要明白线程在哪里需要阻塞(对应PV操作中的P),再找对应的V部分(释放资源)。并且题目这里不要求考察临界资源的访问(互斥关系),只需要考虑同步关系。先想的printB之前需要阻塞,因为需要等A完成打印,所以此处需要Pa操作(如下图),而V部分是资源释放的地方,即A打印后需要Va,即唤醒B可以开始打印了。B和C之间的关系同理。


a同步信号量:可以理解为是B要获取的A打印后的资源,初值为0。

b同步信号量:同理初值为0。

image.png

C++标准库中木有信号量的实现和封装,可以使用C语言的<sempahore.h>。


(1)sem_init函数:需要调用函数所需头文件:semaphore.h


函数原型 :int sem_init(sem_t *sem, int pshared, unsigned int value);

参数解释 :

sem :指向信号量对象

pshared : 指明信号量的类型。当为1时,用于进程;当为0时,用于线程。

value : 指定信号量值的大小

返回值:成功返回0,失败时返回-1,并设置errno。

作用:创建信号量,并为信号量值赋初值。

(2)sem_post函数:需要调用函数所需头文件:semaphore.h


函数原型:int sem_post(sem_t *sem);

参数解释 :

sem :指向信号量对象

返回值:成功返回0,失败时返回-1,并设置errno。

作用: 以原子操作的方式为将信号量增加1

(3)sem_wait:需要调用函数所需头文件:semaphore.h


函数原型:sem_wait(sem_t *sem);

参数解释 :

sem :指向信号量对象

返回值:成功返回0,失败时返回-1,并设置errno

作用: 以阻塞的方式等待信号量,当信号量的值大于零时,执行该函数信号量减一,当信号量为零时,调用该函数的线程将会阻塞。

三、代码

#include <semaphore.h>
class Foo {
private:
    sem_t sem_1, sem_2;
public:
    Foo() {
        sem_init(&sem_1, 0, 0);
        sem_init(&sem_2, 0, 0);
    }
    void first(function<void()> printFirst) {
        // printFirst() outputs "first". Do not change or remove this line.
        printFirst();
        //以原子操作的方式为将信号量增加1
        sem_post(&sem_1);
    }
    void second(function<void()> printSecond) {
        sem_wait(&sem_1);
        // printSecond() outputs "second". Do not change or remove this line.
        printSecond();
        //以原子操作的方式为将信号量增加1
        sem_post(&sem_2);
    }
    void third(function<void()> printThird) {
        sem_wait(&sem_2);
        // printThird() outputs "third". Do not change or remove this line.
        printThird();
    }
};
相关文章
|
7天前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
6天前
|
Java 数据中心 微服务
Java高级知识:线程池隔离与信号量隔离的实战应用
在Java并发编程中,线程池隔离与信号量隔离是两种常用的资源隔离技术,它们在提高系统稳定性、防止系统过载方面发挥着重要作用。
6 0
|
2月前
|
安全 C++
利用信号量实现线程顺序执行
【8月更文挑战第25天】信号量是多线程编程中用于控制共享资源访问的关键同步机制,能有效保证线程按预设顺序执行。实现方法包括:引入相关头文件(如 C++ 中的 `&lt;semaphore.h&gt;`),创建信号量并通过 `sem_init` 设置初始值;在各线程函数中运用 `sem_post` 与 `sem_wait` 来传递执行权;最后,通过 `sem_destroy` 销毁信号量以释放资源。使用过程中需注意错误处理、确保线程安全及合理设定信号量初值,以维持程序稳定性和高效性。
|
2月前
利用信号量实现线程顺序执行
【8月更文挑战第24天】本文介绍了如何运用信号量确保多线程程序中线程按预定顺序执行的方法。信号量作为同步机制,可有效控制共享资源访问,防止数据不一致。实现步骤包括:引入必要的头文件(如 `&lt;pthread.h&gt;` 和 `&lt;semaphore.h&gt;`),定义信号量变量(如 `sem_t` 类型),初始化信号量(通常第一个信号量设为1,其余设为0),以及创建线程(每个线程执行特定任务并释放相应信号量)。
|
2月前
|
数据采集 Java Python
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
python 递归锁、信号量、事件、线程队列、进程池和线程池、回调函数、定时器
|
3月前
|
监控 Cloud Native Java
通用快照方案问题之Hystrix和Ribbon在超时设置上的冲突如何解决
通用快照方案问题之Hystrix和Ribbon在超时设置上的冲突如何解决
38 0
|
4月前
|
API
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
java-多线程-CountDownLatch(闭锁) CyclicBarrier(栅栏) Semaphore(信号量)-
28 1
|
5月前
|
安全 Java API
多线程(JUC, ReentrantLock, 原子类, 线程池, 信号量 Semaphore, CountDownLatch)
多线程(JUC, ReentrantLock, 原子类, 线程池, 信号量 Semaphore, CountDownLatch)
48 4
|
5月前
|
算法 安全 Unix
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
【C++ 20 信号量 】C++ 线程同步新特性 C++ 20 std::counting_semaphore 信号量的用法 控制对共享资源的并发访问
148 0
|
5月前
Leetcode之多线程编程题
现有函数 printNumber 可以用一个整数参数调用,并输出该整数到控制台。 例如,调用 printNumber(7) 将会输出 7 到控制台。 给你类 ZeroEvenOdd 的一个实例,该类中有三个函数:zero、even 和 odd 。ZeroEvenOdd 的相同实例将会传递给三个不同线程: