【LeetCode】1114. Print in Order 解题报告(C++)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/print-in-order/
题目描述
Suppose we have a class:
public class Foo {
public void first() { print("first"); }
public void second() { print("second"); }
public void third() { print("third"); }
}
The same instance of Foo will be passed to three different threads. Thread A will call first(), thread B will call second(), and thread C will call three(). Design a mechanism and modify the program to ensure that second() is executed after first(), and third() is executed after second().
Example 1:
Input: [1,2,3]
Output: "firstsecondthird"
Explanation: There are three threads being fired asynchronously. The input [1,2,3] means thread A calls first(), thread B calls second(), and thread C calls third(). "firstsecondthird" is the correct output.
Example 2:
Input: [1,3,2]
Output: "firstsecondthird"
Explanation: The input [1,3,2] means thread A calls first(), thread B calls third(), and thread C calls second(). "firstsecondthird" is the correct output.
Note:
We do not know how the threads will be scheduled in the operating system, even though the numbers in the input seems to imply the ordering. The input format you see is mainly to ensure our tests’ comprehensiveness.
题目大意
现在三个线程,每个线程分别调用三个函数中的一个。无论线程的产生和调用关系怎么样,最终输出的结果要求都是"firstsecondthird"。如何设计是三个函数。
解题方法
mutex锁
这个是Leetcode的新题型,也就是说并发类型,我觉得很实用,工作中能用到。
一般情况下,最简单的协调不同线程之间的调度关系,都可以使用mutex来做,本质是信号量。
std::mutex 的成员函数有四个:
构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
- (1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
- (2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
- (3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
unlock(), 解锁,释放对互斥量的所有权。try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况,
- (1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
- (2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
- (3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
也就是说一个锁能控制两个线程的执行顺序。这个题中我们需要保持三个函数是按顺序执行的,则需要两个锁m1和m2。
在开始的时候,两个锁都锁起来。first()可以直接执行,second()等待m1释放之后执行,third()等待m2释放之后执行。first()结束之后释放m1,second()结束之后释放m2.因此三个的顺序都协调一致了。
C++代码如下:
class Foo {
private:
mutex m1, m2;
public:
Foo() {
m1.lock();
m2.lock();
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
m1.unlock();
}
void second(function<void()> printSecond) {
m1.lock();
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
m1.unlock();
m2.unlock();
}
void third(function<void()> printThird) {
m2.lock();
// printThird() outputs "third". Do not change or remove this line.
printThird();
m2.unlock();
}
};
void printFirst() {
cout << "first";
}
void printSecond() {
cout << "second";
}
void printThird() {
cout << "third";
}
promise/future
这也是C++11中的新特性,可以把promise和future当做是在不同线程之间传递值的方式。在某个线程中对promise中生产一个数据,可以在另外一个线程中从future中获取这个数据。
- promise和future是绑定在一起的,可以调用promise::get_future()获取与其绑定的future。
- future.wait()方法对当前的线程进行阻塞,等待与其绑定的promise调用set_value()方法。
- future.get()方法对当前的线程进行阻塞,等待与其绑定的promise调用set_value()方法的返回值。
因此实现线程的同步的方法会很方便。C++代码如下:
class Foo {
private:
std::promise<void> p1;
std::promise<void> p2;
public:
Foo() {
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
p1.set_value();
}
void second(function<void()> printSecond) {
p1.get_future().wait();
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
p2.set_value();
}
void third(function<void()> printThird) {
p2.get_future().wait();
// printThird() outputs "third". Do not change or remove this line.
printThird();
}
};
void printFirst() {
cout << "first";
}
void printSecond() {
cout << "second";
}
void printThird() {
cout << "third";
}
参考资料:
日期
2019 年 7 月 14 日 —— 第一次做并发的题
【LeetCode】1114. Print in Order 解题报告(C++)的更多相关文章
- LeetCode 2 Add Two Sum 解题报告
LeetCode 2 Add Two Sum 解题报告 LeetCode第二题 Add Two Sum 首先我们看题目要求: You are given two linked lists repres ...
- 【LeetCode】376. Wiggle Subsequence 解题报告(Python)
[LeetCode]376. Wiggle Subsequence 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.c ...
- 【LeetCode】649. Dota2 Senate 解题报告(Python)
[LeetCode]649. Dota2 Senate 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
- 【LeetCode】593. Valid Square 解题报告(Python)
[LeetCode]593. Valid Square 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地 ...
- 【LeetCode】498. Diagonal Traverse 解题报告(Python)
[LeetCode]498. Diagonal Traverse 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: htt ...
- 【LeetCode】386. Lexicographical Numbers 解题报告(Python)
[LeetCode]386. Lexicographical Numbers 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博 ...
- 【LeetCode】722. Remove Comments 解题报告(Python)
[LeetCode]722. Remove Comments 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/remove-c ...
- 【LeetCode】86. Partition List 解题报告(Python)
[LeetCode]86. Partition List 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http:// ...
- 【LeetCode】911. Online Election 解题报告(Python)
[LeetCode]911. Online Election 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ ...
随机推荐
- python14异常处理
def test_div(num1,num2): return num1 / num2 if __name__ == "__main__": try: print(test_div ...
- SIG -MESH -1
协议栈 node:成为蓝牙mesh网络中一员的设备被称为节点(Node). 蓝牙mesh规格定义了节点可能拥有的特性.具有这些特性中的一个或多个,即表示节点可以在网络中扮演相应的特殊角色.定义的 ...
- 游戏案例|Service Mesh 在欢乐游戏的应用演变和实践
作者 陈智伟,腾讯 12 级后台专家工程师,现负责欢乐游戏工作室公共后台技术研发以及团队管理工作.在微服务分布式架构以及游戏后台运维研发有丰富的经验. 前言 欢乐游戏工作室后台是分布式微服务架构,目前 ...
- nit是虱子的卵
如题.[牛津] (egg of a) louse or other parasitic insect 虱或其他寄生虫(的卵). 忘了在那个帖子里说nit: 虱子了. 为了凑字数,迄今为止六级/考研单词 ...
- Linux 内存泄漏 valgrind
Valgrind 是个开源的工具,功能很多.例如检查内存泄漏工具---memcheck. Valgrind 安装: 去官网下载: http://valgrind.org/downloads/curre ...
- 单体内置对象 Global 和 Math
单体内置对象 Global 和 Math 在所有代码执行前,作用域中就已经存在两个内置对象:Global(全局)和Math.在大多数ES实现中都不能直接访问Global对象.不过,WEB浏览器实现了承 ...
- map/multimap深度探索
map/multimap同样以rb_tree为底层结构,同样有元素自动排序的特性,排序的依据为key. 我们无法通过迭代器来更改map/multimap的key值,这个并不是因为rb_tree不允许, ...
- 转 Android 多线程:手把手教你使用AsyncTask
转自:https://www.jianshu.com/p/ee1342fcf5e7 前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 ...
- jenkins之代码部署回滚脚本
#!/bin/bash DATE=`date +%Y-%m-%d_%H-%M-%S` METHOD=$1 BRANCH=$2 GROUP_LIST=$3 function IP_list(){ if ...
- [项目总结]关于调用系统照相机Activity被销毁问题解决
在项目中需要启用系统照相机来拍照.本来很容易的一个问题.但在适配中出现了问题. 简单说一下问题: 有些手机拍照成功,有些手机拍完照后确定返回后activity数据丢失,被销毁了. 问题查找: 经过代码 ...