누군가가 간단한 용어로 방해 요인 패턴을 설명 할 수 있습니까?


답변:


33

파울러 기술 제공 업체 좋은 프라이머,이 설명 :

원유 수준에서 Disruptor는 생산자가 별도의 다운 스트림 대기열을 통해 병렬 소비를 위해 모든 소비자에게 전송되는 객체를 배치하는 대기열의 멀티 캐스트 그래프로 생각할 수 있습니다. 내부를 보면이 대기열 네트워크가 실제로 단일 데이터 구조 인 링 버퍼라는 것을 알 수 있습니다.

각 생산자와 소비자는 현재 작업중인 버퍼의 슬롯을 나타내는 시퀀스 카운터를 가지고 있습니다. 각 생산자 / 소비자는 자체 시퀀스 카운터를 작성하지만 다른 시퀀스 카운터를 읽을 수 있습니다. 이런 식으로 생산자는 소비자의 카운터를 읽고 카운터에 잠금 없이도 쓰기를 원하는 슬롯을 사용할 수있게합니다. 마찬가지로 소비자는 카운터를 보면서 다른 소비자가 메시지를 처리 ​​한 후에 만 ​​메시지를 처리하도록 할 수 있습니다.

여기에 이미지 설명을 입력하십시오

보다 일반적인 접근 방식은 잠금 장치를 동시성 메커니즘으로 사용하는 생산자 대기열과 소비자 대기열을 사용할 수 있습니다. 실제로, 생산자 및 소비자 큐에서 발생하는 일은 큐가 완전히 비어 있거나 대부분 가득 찼기 때문에 잠금 경합이 발생하고 클럭 사이클이 낭비된다는 것입니다. 방해자는 부분적으로 모든 생산자와 소비자가 동일한 큐 메커니즘을 사용하게하여 잠금 메커니즘을 사용하지 않고 시퀀스 카운터를 보면서 서로 조정함으로써이를 완화합니다.


9

CoralQueue 에 대한이 기사에서 :

중단 자 패턴은 메모리 장벽을 사용하여 시퀀스를 통해 생산자와 소비자를 동기화하는 사전 할당 된 전송 객체로 채워진 원형 배열 (예 : 링 버퍼)로 백업되는 배치 대기열입니다.

따라서 생산자와 소비자는 해당 배열 을 확인 하여 원형 배열 내부에서 서로 밟지 않습니다 . 그리고 시퀀스를 서로주고 받으려면 잠금 대신 메모리 장벽을 사용합니다. 이것이 가장 빠른 잠금 방식으로 통신 할 수 있습니다.

다행스럽게도 사용하기 위해 방해 요소 패턴의 내부 세부 정보를 확인할 필요가 없습니다. LMAX 구현 외에도 Coral Blocks가 개발 한 CoralQueue있으며, 여기에는 나와 제휴되어 있습니다. 어떤 사람들은 코드를 읽음으로써 개념을 이해하기가 더 쉽다는 것을 알고 있습니다. 아래는 단일 생산자가 단일 소비자에게 메시지를 보내는 간단한 예입니다. 디멀티플렉서 (하나의 생산자에서 많은 소비자로) 예제에 대해서도이 질문 을 확인할 수 있습니다 .

package com.coralblocks.coralqueue.sample.queue;

import com.coralblocks.coralqueue.AtomicQueue;
import com.coralblocks.coralqueue.Queue;
import com.coralblocks.coralqueue.util.Builder;

public class Basics {

    public static void main(String[] args) {

        final Queue<StringBuilder> queue = new AtomicQueue<StringBuilder>(1024, new Builder<StringBuilder>() {
            @Override
            public StringBuilder newInstance() {
                return new StringBuilder(1024);
            }
        });

        Thread producer = new Thread(new Runnable() {

            private final StringBuilder getStringBuilder() {
                StringBuilder sb;
                while((sb = queue.nextToDispatch()) == null) {
                    // queue can be full if the size of the queue
                    // is small and/or the consumer is too slow

                    // busy spin (you can also use a wait strategy instead)
                }
                return sb;
            }

            @Override
            public void run() {

                StringBuilder sb;

                while(true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to send a message to
                    // the other thread you can just do:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hello!");
                    queue.flush();

                    // you can also send in batches to increase throughput:
                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi!");

                    sb = getStringBuilder();
                    sb.setLength(0);
                    sb.append("Hi again!");

                    queue.flush(); // dispatch the two messages above...
                }
            }
        }, "Producer");

        Thread consumer = new Thread(new Runnable() {

            @Override
            public void run() {

                while (true) { // the main loop of the thread

                    // (...) do whatever you have to do here...

                    // and whenever you want to check if the producer
                    // has sent a message you just do:

                    long avail;
                    while((avail = queue.availableToPoll()) == 0) {
                        // queue can be empty!
                        // busy spin (you can also use a wait strategy instead)
                    }

                    for(int i = 0; i < avail; i++) {
                        StringBuilder sb = queue.poll();
                        // (...) do whatever you want to do with the data
                        // just don't call toString() to create garbage...
                        // copy byte-by-byte instead...
                    }
                    queue.donePolling();
                }
            }
        }, "Consumer");

        consumer.start();
        producer.start();
    }
}

면책 조항 : 저는 CoralQueue 개발자 중 한 명입니다.


1
설명하는 소프트웨어와의 제휴 관계를 밝히면 좋을 것입니다.
Deer Hunter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.