简体   繁体   English

我可以“强制”线程唤醒吗?

[英]Can I “force” thread to wake up?

I want to implement a fast logger, that holds log entries, and when a certain trigger arrives, it flushes the last X messages. 我想实现一个保存日志条目的快速记录器,当某个触发器到达时,它将刷新最近的X条消息。

So the idea is to hold all the messages in a cyclic buffer, and once we have the trigger, to push it's ID to a queue, which another thread monitors(one thread in all the system). 因此,想法是将所有消息保存在循环缓冲区中,一旦有了触发器,便将其ID推送到另一个线程监视的队列(整个系统中的一个线程)。 this thread will go back X messages and to flush them. 该线程将返回X消息并刷新它们。 I know how to deal with messages that are being written while I am trying to flush, messages that have been overwritten before I flushed messages that being flushed while I am trying to update them etc. 我知道如何处理尝试刷新时写入的消息,刷新之前刷新的消息等在尝试刷新它们之前被覆盖的消息等。

My problem is, if for example I have 20 threads writing messages, and only 10 cores, in the time deference between 2 "writer" thread's execution, all the buffer will be overwritten several times. 我的问题是,例如,如果我有20个线程编写消息,而只有10个内核,则在执行2个“ writer”线程之间的时间上,所有缓冲区将被覆盖多次。

Is there any way that "my" thread can "force" the "writer" thread to execute(or to give it it's time slice? I guess no but still... can you advice on any other way/design to overcome this problem. 有什么办法可以使“我的”线程“强制”执行“作者”线程(或给它时间片吗?我想不,但还是...您可以建议其他方法或设计来克服这个问题吗? 。

As I understand you want to resume your thread as soon as there are new ID's in the queue available. 据我了解,您希望在队列中有新ID时立即恢复线程。 It's possible with locking primitives — your writer thread should sleep until notified from your trigger thread. 锁定原语是可能的-您的编写器线程应该休眠,直到从触发线程通知为止。 How to achieve this behavior depends on multithreading framework you are using. 如何实现此行为取决于您使用的多线程框架。

For example, in C++11 you can have a look at std::condition_variable . 例如,在C ++ 11中,您可以查看std::condition_variable

Edit. 编辑。 As mentioned in the comments, the disk IO is slow, so you need to fetch the messages to memory in the writer thread, and only then write them to disk. 如注释中所述,磁盘IO速度很慢,因此您需要将消息提取到写入线程中的内存中,然后再将它们写入磁盘。 During IO the buffer can be overwritten by the arriving messages. 在IO期间,缓冲区可以被到达的消息覆盖。

I've written something similar before, where calls to log methods are actually placed on a queue which another thread ( T-Logger ) monitors. 我之前写过类似的文章,其中对log方法的调用实际上放置在另一个线程( T-Logger )监视的队列上。 This frees up the other threads from having to having to call the underlying log APIs and works well in low latency applications. 这使其他线程从不必调用底层日志API的工作中解放了出来,并且在低延迟应用程序中运行良好。

If you want to explicitly buffer and then write on a trigger then I'd still recommend doing all the writes from one thread, such as T-Logger and then use some sort of conditional variable to signal to T-Logger that it should now go and write the items in the queue to the underlying log file. 如果要显式缓冲然后在触发器上写,那么我仍然建议从一个线程(例如T-Logger执行所有写操作,然后使用某种条件变量T-Logger发出信号,表明它现在应该执行并将队列中的项目写入基础日志文件。

As mentioned in the question comments, you should avoid having multiple threads trying to do IO. 如问题注释中所述,应避免让多个线程尝试执行IO。 IO is incredible slow, and having all your threads trying to write to a file will cause them to give up their CPU cycles waiting for the IO to complete. IO令人难以置信的缓慢,让所有线程尝试写入文件将导致它们放弃等待IO完成的CPU周期。

Sounds like a classic case to use a semaphore, initialized with the length of the circular buffer. 听起来像使用信号量的经典案例,并使用循环缓冲区的长度对其进行了初始化。 The log call from the threads needing to log stuff has to get a unit from the semaphore before proceeding and the logging thread signals the semaphore when it extracts an entry from the queue. 需要进行日志处理的线程的日志调用必须在继续之前从信号量中获取一个单位,并且日志线程在从队列中提取条目时会向信号量发出信号。 If the buffer runs out, any thread trying to log will then block until there is space for its log entry. 如果缓冲区用完,则任何试图记录的线程都将阻塞,直到有足够的空间可以记录其日志。

Obviously, the circular buffer/queue/whatever container for the log entries must be thread-safe. 显然,日志条目的循环缓冲区/队列/任何容器必须是线程安全的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM