Disruptor pattern LMAX中断器:EventHandler必须克隆从EventHandler#OneEvent接收的对象吗

Disruptor pattern LMAX中断器:EventHandler必须克隆从EventHandler#OneEvent接收的对象吗,disruptor-pattern,lmax,Disruptor Pattern,Lmax,我有一个与许多生产者和消费者的应用程序 据我所知,RingBuffer在RingBuffer init开始时创建对象,然后在Ring中发布时复制对象,并在EventHandler中从中获取它们 我的应用程序LogHandler缓冲列表中接收到的事件,以便在列表达到一定大小后以批处理模式进一步发送。因此EventHandler#onEvent将接收到的对象放入列表中,一旦它达到大小,它将以RMI的形式发送到服务器并清除它 我的问题是,我是否需要在我放入列表之前克隆对象,据我所知,一旦被消耗,它们就

我有一个与许多生产者和消费者的应用程序

据我所知,RingBuffer在RingBuffer init开始时创建对象,然后在Ring中发布时复制对象,并在EventHandler中从中获取它们

我的应用程序LogHandler缓冲列表中接收到的事件,以便在列表达到一定大小后以批处理模式进一步发送。因此EventHandler#onEvent将接收到的对象放入列表中,一旦它达到大小,它将以RMI的形式发送到服务器并清除它

我的问题是,我是否需要在我放入列表之前克隆对象,据我所知,一旦被消耗,它们就可以被重用


我是否需要同步访问EventHandler#OneEvent中的列表?

是-您的理解是正确的。您可以在ringbuffer插槽中复制和复制值

我建议您在从环形缓冲区提取值并将其提取到事件处理程序列表中时克隆这些值;否则,插槽可以重复使用

只要列表是事件处理程序的私有成员变量,并且每个线程只有一个事件处理程序实例,就不需要同步对列表的访问。如果有多个事件处理程序添加到同一个(如静态)列表实例,则需要同步


澄清:

请务必阅读下面OzgurH评论中的背景。如果您坚持在disruptor上使用endOfBatch标志并使用该标志确定批处理的大小,则不必将对象从列表中复制出来。如果您使用的是自己的累积策略(例如大小-根据问题),那么您应该将对象克隆出来,因为在您有机会发送之前,插槽可以重用


还值得注意的是,如果您需要在列表实例上进行同步,那么您就错过了使用disruptor的一个大好机会,并且无论如何都会破坏您的性能。

是-您的理解是正确的。您可以在ringbuffer插槽中复制和复制值

我建议您在从环形缓冲区提取值并将其提取到事件处理程序列表中时克隆这些值;否则,插槽可以重复使用

只要列表是事件处理程序的私有成员变量,并且每个线程只有一个事件处理程序实例,就不需要同步对列表的访问。如果有多个事件处理程序添加到同一个(如静态)列表实例,则需要同步


澄清:

请务必阅读下面OzgurH评论中的背景。如果您坚持在disruptor上使用endOfBatch标志并使用该标志确定批处理的大小,则不必将对象从列表中复制出来。如果您使用的是自己的累积策略(例如大小-根据问题),那么您应该将对象克隆出来,因为在您有机会发送之前,插槽可以重用


还值得注意的是,如果您需要在列表实例上进行同步,那么您已经错过了使用disruptor的一个大好机会,并且无论如何都会破坏您的性能。

可以在不克隆/复制值的情况下使用disruptor的RingBuffer中的插槽(包括包含
列表的插槽)。这对于您来说可能是一个更好的解决方案,这取决于您是否担心垃圾的创建,以及您是否确实需要关心对放置在RingBuffer中的对象的并发更新。如果放置在插槽列表中的所有对象都是不可变的,或者如果它们一次只由一个线程更新/读取(中断程序通常用于强制执行的先决条件),那么克隆它们将毫无益处,因为它们已经不受数据争用的影响


关于批处理,请注意,Disruptor框架本身提供了一种机制,用于在EventHandler线程中从RingBuffer中批量获取项目。这是一种完全线程安全且无锁的方法,通过使CPU更容易预测内存访问模式,可以产生更好的性能。

可以使用中断器的环形缓冲区中的插槽(包括包含
列表的插槽),而无需克隆/复制值。这对于您来说可能是一个更好的解决方案,这取决于您是否担心垃圾的创建,以及您是否确实需要关心对放置在RingBuffer中的对象的并发更新。如果放置在插槽列表中的所有对象都是不可变的,或者如果它们一次只由一个线程更新/读取(中断程序通常用于强制执行的先决条件),那么克隆它们将毫无益处,因为它们已经不受数据争用的影响


关于批处理,请注意,Disruptor框架本身提供了一种机制,用于在EventHandler线程中从RingBuffer中批量获取项目。这是一种完全线程安全且无锁的方法,通过使CPU更容易预测内存访问模式,可以产生更好的性能。

Re:“我建议您在从环形缓冲区提取值并将其提取到事件处理程序列表中时克隆这些值;否则可以重用插槽”这句话,请看一下@Michael Barker的文章,以及我最近对它的评论。它并不完全适用于OP的执行流,但是如果在使用
endOfBatch==true
从事件处理程序返回之前处理相同的批处理事件,则不需要克隆事件数据,对吗?是@OzgurH这是一个好观点。你是对的,你可以等到endOfBatch释放对象,我不知道这个行为应该是合同的一部分,所以很高兴知道。我已经用澄清更新了回复。我仍然认为对于最初的问题,他们应该打算复制对象,因为问题上下文包括按大小进行批处理(我假设这意味着他们将复制对象)