【问题标题】:multithreaded one read one write time_t多线程一读一写time_t
【发布时间】:2017-08-16 10:29:14
【问题描述】:

我正在编写一个有 2 个线程的多线程应用程序。 其中一个线程从队列中接收数据并将其聚合,另一个线程将聚合后的数据发送到服务器。

我希望能够知道上次收到数据的时间,所以我使用:

time_t last_data = time(NULL)

获取每个事件的正确时间(我不需要它非常准确,但我需要它快速),然后另一个发送这个值和聚合数据。

我的问题是:

  1. 即使获取最新更新不是很重要,我是否也必须进行同步?
  2. 我用std::atomic<time_t>测试了一下,好像有一些性能问题,有没有其他更快的方法?
  3. 如果我不同步读/写,最坏的情况是什么?
  4. 有没有比time(NULL) 更快的方法来获取当前时间(不必非常准确)?

更新

这是我的应用程序工作流程的解释。

应用需求: 1.使用IPC(目前nanomsg)从外部来源消费数据。 2. 将数据聚合成批量。 3. 每隔给定的时间间隔(1 秒)将聚合数据发送到远程服务器。

当前实现:

  1. 创建 2 个缓冲区来保存聚合数据(一个用于接收,一个用于发送)。
  2. 创建一个消费者线程来消费来自 IPC 的数据并填充接收缓冲区。
  3. 创建将数据发送到服务器的发送线程。
  4. 发送线程的每次迭代都会交换缓冲区(交换指针和使用互斥锁进行锁定)并将数据发送到服务器。

我不希望消费者在网络 IO 上等待,所以我创建了这个流程。 我可以在这里使用事件驱动来代替这种没有所有锁定的复杂机制吗(目前它工作正常,但我相信它会更好)?

【问题讨论】:

  • 你为什么要做多线程?
  • 因为我不想在发送到服务器时阻止队列中的消费
  • 我是这么想的,请看下面的答案。
  • 问题 1 和 3 无法回答:参见问题 1 中的“this”一词。“this”是什么?看起来您正在尝试同步两个线程,这是正确的。如果是这样,那么使用线程不是一个好主意。线程应该大部分独立,几乎没有同步。如果它们花费大量时间阻塞/同步,那么这表明它们应该是一个线程。
  • 为什么使用 C 中的库函数而不是 C++。 std::chrono::steady_clock::now()呢?

标签: c++ multithreading c++11


【解决方案1】:

不要那样做。你只需要一个线程。您可以使用 select/poll/epoll。这些可以等待您的输入,同时等待您的输出完成。您将进行事件驱动编程和非阻塞输出。这是值得学习的东西。一开始有点困难,但很快就会让生活变得更轻松,即没有你现在遇到的问题。程序也会更快。

【讨论】:

  • 这是建议,而不是实际答案。
  • 这是基本问题的答案,我如何让我的程序做我想做的事。这个问题是一个XY问题。我正在尝试做 Y,我认为我应该通过做 X 来做到这一点。我不能做 X,所以我问如何做 X。我回答了如何做 Y。
  • 你的想法是基于假设的。 OP 没有提供足够的架构信息。
  • @AndrejsCainikovs 这是真的,我假设他们使用的是 Unix(UNIX、BSD、MacOs、Gnu)。他们可能正在运行一些嵌入式系统(尽管其中很多都允许事件驱动)。微软的 Windows(据我所知)不允许在 C++ 中这样做(但在 C# 中允许)。但是微软没有 C++11 编译器。
【解决方案2】:

假设一个线程执行:

last_data = time(NULL);

而另一个使用last_data,但两者之间没有同步事件,则无法保证last_data的修改值何时或是否对读取线程可见。

然而最严重的可能是time_t(可能是long)的写入不是原子的,另一个线程可能会读取损坏的“部分写入”值。 这可能会导致延迟和时间计算出现故障,从而影响下游流程。

您可能会分析您的程序并发现由于两者交互,因此在某些时候有足够的内存围栏来保证最终更新。

注意:这是一种奇怪的情况,我怀疑您认为某些内容不同步,但确实如此!通常的经验是相反的......

基本上没有足够的信息来了解您遇到的问题。 例如,如果读取器线程是读取时间的唯一进程,我希望看到如下代码:

线程 1: 如果收到数据,锁定 L,更新时间,加入队列,解锁 L。 线程 2: 如果队列 L 中的项目,读取队列和更新时间,解锁 L .. 处理项目。

在这种情况下,时间已经同步了。

请提供一个最小的、完整的、可验证的例子……

【讨论】:

    猜你喜欢
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2012-08-18
    相关资源
    最近更新 更多