查看: 2333| 回复: 6
跳转到指定楼层
上一主题 下一主题
收起左侧

[高频题] 一道描述很简洁并且涉及C++高级语言特性的题目

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
题目的描述很简单,就是实现一个机制使得可以很容易地在多线程情况下serialize输出流(例如cout / cerr)—— 估计大多数debug过多线程程序的人都遇到过这样的需求,而且这个问题目前Stack Overflow上并没有比较好的答案。

举个例子,如果让两个线程同时循环执行下面这句输出语句:
--
std::cout << "This is thread " << id << std::endl;
--

那么默认的cout的原子性只作用到单个<<符号,也就是说输出并不一定是
--
This is thread 1
This is thread 2
...
--
这样一句一句的打出来,而可能会变成
--
This is thread This is thread 1
2
...
--
这样。也就是说一个线程的一整句话还没打完,另一个线程的输出就插进来了。

那么,为了比较优雅地处理这种多线程情况下完整输出一句话的需求,我们希望设计一个类似Java下面synchronized关键字的机制,使得每个线程只要用下列语句:
--
synchronized(std::cout) << "This is thread " << id << "\n";
--
就能保证输出时单个statement的完整性。

题目就是问这个synchronized该如何实现?


PS:这个问题其实挺适合当C++面试题的,因为它涉及到某个只有C++有而C无法模拟的特性,以及对对象生存期的理解。

评分

参与人数 2大米 +8 收起 理由
Lunluen + 2 很有用的信息!
14417335 + 6 很有用的信息!

查看全部评分


上一篇:利口换界面了吗
下一篇:问一道combination sum变种题

本帖被以下淘专辑推荐:

  • · 刷题|主题: 55, 订阅: 17
推荐
 楼主| magicsets 2019-5-27 16:23:37 | 只看该作者
全局:
上面两个答案都是正确的,各有适用的场景

这里再稍微解释一下.. 主帖里所说的C++特有的特性就是RAII(Resource Acquisition Is Initialization),例如std::unique_ptr、std::lock_guard都是典型的RAII应用。更多的介绍网上有很多,比如这个: https://oxnz.github.io/2015/07/23/cpp-raii/

而C基本上是无法模拟RAII特性的,即使用macro糊出来一个也不具有composability(简单来说就是不好用),用C写的代码如果涉及多种资源的分配释放并且中间有abort逻辑的话,一般是在函数底部写一串label然后各种goto,比如这个:https://vilimpoc.org/research/raii-in-c/

此外楼上Airtnp回答了对象生存期的相关内容,也就是对于 synchronized(std::cout) << "This is thread " << id << "\n" 这样的表达式,临时对象synchronized(std::cout)的生存期是长于其所在整体表达式的生存期的,所以“synchronized”的destructor会在所有“<<”都执行完之后才执行。

评分

参与人数 1大米 +1 收起 理由
rrrl8523690 + 1 很有用的信息!

查看全部评分

回复

使用道具 举报

推荐
Airtnp 2019-5-24 09:26:30 | 只看该作者
全局:
LB4195450681 发表于 2019-5-24 04:30
多谢分享,以前从不知道20有这样的东西。不过Only available in C++20感觉短时间无法用到啊...

https://wandbox.org/permlink/sjTy71dtqDcK1iqW

我就随便写写举个例子哈...没测过但这么做当玩具用应该就行了
libstdc++和libcxx都还没实现(
回复

使用道具 举报

推荐
rrrl8523690 2019-5-23 13:09:14 | 只看该作者
全局:
  1. #include <algorithm>
  2. #include <future>
  3. #include <iostream>
  4. #include <map>
  5. #include <memory>
  6. #include <mutex>
  7. #include <queue>
  8. #include <set>
  9. #include <vector>

  10. using namespace std;

  11. template <typename Stream> class SyncStream {
  12. public:
  13.   SyncStream(Stream &stream) : stream_(&stream) { mutex_.lock(); }

  14.   ~SyncStream() { mutex_.unlock(); }

  15.   template <typename T> SyncStream &operator<<(const T &rhs) {
  16.     (*stream_) << rhs;
  17.     return *this;
  18.   }

  19.   SyncStream &operator<<(std::ostream &(*manip)(std::ostream &)) {
  20.     (*stream_) << manip;
  21.     return *this;
  22.   }

  23. private:
  24.   static std::mutex mutex_;
  25.   Stream *stream_;
  26. };

  27. template <typename Stream> std::mutex SyncStream<Stream>::mutex_;

  28. template <typename Stream> SyncStream<Stream> synchronized(Stream &stream) {
  29.   return SyncStream<Stream>(stream);
  30. }

  31. int main() {
  32.   const int n = 100;
  33.   std::vector<std::future<void>> futures(n);
  34.   for (int i = 0; i < n; ++i) {
  35.     futures[i] = std::async(std::launch::async, [i]() {
  36.       std::this_thread::sleep_for(std::chrono::milliseconds(1));
  37.       synchronized(std::cout) << "thread id " << i << std::endl;
  38.     });
  39.   }
  40.   for (const auto &future : futures) {
  41.     future.wait();
  42.   }
  43.   return 0;
  44. }
复制代码



不知道是否正确,manip的部分是从SO一个回答上抄的

评分

参与人数 1大米 +1 收起 理由
wchoice + 1 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
忘记密码 2018-11-13 11:02:34 | 只看该作者
全局:
PS:这个问题其实挺适合当C++面试题的,因为它涉及到某个只有C++有而C无法模拟的特性,以及对对象生存期的理解。


几个月前面试遇到
回复

使用道具 举报

🔗
Airtnp 2019-5-22 17:47:14 | 只看该作者
全局:
https://en.cppreference.com/w/cpp/io/basic_osyncstream

scope里存
dtor一起交

补充内容 (2019-5-23 21:18):
lifetime ends when whole expression ends,所以直接写在最前面也行
回复

使用道具 举报

🔗
falah325 2019-5-24 04:30:29 | 只看该作者
全局:
Airtnp 发表于 2019-5-22 17:47
https://en.cppreference.com/w/cpp/io/basic_osyncstream

scope里存

多谢分享,以前从不知道20有这样的东西。不过Only available in C++20感觉短时间无法用到啊...
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表