두 개의 스레드를 "정확히"동시에 시작하는 방법


91

스레드는 동일한 분할 초에 시작해야합니다. 을 (를) 수행 thread1.start()하면 다음에을 (를) 실행하기까지 몇 밀리 초가 걸릴 것임을 이해 thread2.start()합니다.

가능하거나 불가능합니까?


2
분할 초는 GHz 속도에서 매우 긴 시간입니다.
Nikolai Fetissov

30
그렇게 강렬하게 반대 투표 할 필요가 없습니다. 모든 사람이 스레딩과 관련된 비결정론을 이해하는 것은 아니며 우리 모두 어딘가에서 시작해야합니다.
Michael Petrotta

7
반대표를 이해하지 못합니다. 스레드 간의 동기화는 매우 일반적인 필요성입니다. 예, Java에서는 정확히 병렬로 실행할 수 없습니다 (다른 플랫폼에서는 매우 유효한 요구 사항 btw 일 수 있음).하지만 때때로 작업을 동기화해야하는 경우가 매우 흔합니다. 이것이 jdk에 클래스가있는 이유입니다. 어쩌면 .. 문구는 정확하지 않았다, 그러나 그는 알고 원하는 경우 도대체, 그는 질문을하지 않았을
Enno시오 지

글쎄, 나는 당신의 모든 분노를 이해한다고 생각합니다. 인터뷰에서 물어 본 질문이었는데 ... 아마도 속임수 였나 봐 Q.하지만 헷갈려서 확인하고 싶었어요. 그것이 가능한지 물은 이유입니다.
피가로

2
@javaguy- "속임수"질문이 아닙니다. 오히려 일반적인 멀티 스레드 프로그래밍을 얼마나 잘 이해하고 있는지 알아보기 위해 선택한 질문입니다. 자바의 경우도 마찬가지입니다.
Stephen C

답변:


135

스레드를 정확히 동시에 시작하려면 (최소한 가능한 한 좋게) CyclicBarrier를 사용할 수 있습니다 .

// We want to start just 2 threads at the same time, but let's control that 
// timing from the main thread. That's why we have 3 "parties" instead of 2.
final CyclicBarrier gate = new CyclicBarrier(3);

Thread t1 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};
Thread t2 = new Thread(){
    public void run(){
        gate.await();
        //do stuff    
    }};

t1.start();
t2.start();

// At this point, t1 and t2 are blocking on the gate. 
// Since we gave "3" as the argument, gate is not opened yet.
// Now if we block on the gate from the main thread, it will open
// and all threads will start to do stuff!

gate.await();
System.out.println("all threads started");

이것은 일 필요는 없으며 CyclicBarrier, CountDownLatch또는 잠금을 사용할 수도 있습니다 .

이것은 여전히 표준 JVM에서 정확히 동시에 시작 되는지 확인할 수는 없지만 거의 비슷할 수 있습니다. 예를 들어 성능 테스트를 수행 할 때 꽤 가까워지는 것이 여전히 유용합니다. 예를 들어 서로 다른 수의 스레드를 사용하여 데이터 구조의 처리량을 측정하려는 경우 이러한 종류의 구조를 사용하여 가능한 가장 정확한 결과를 얻으려고합니다.

다른 플랫폼에서는 스레드를 정확히 시작 하는 것이 매우 유효한 요구 사항 일 수 있습니다.


5
+1 좋은 생각 ;-) 물론 스레드 가 실시간으로 정확히 같은 시간에 시작하도록 만들지는 않지만 (적어도 단일 코어 칩에서는 아니고 멀티 코어 칩에서도 보장되지는 않습니다),하지만 더 잘할 수있는 방법이 없습니다.
David Z

이 후크가 환경 별 대기 핸들에 연결됩니까?
ChaosPandion

@ChaosPandion : 자세히 설명 하시겠습니까?
Santa

@Santa-예를 들어 Win32 API는 다양한 기본 요소를 제공합니다. 한 가지 유용한 유형은를 호출 할 때 반환되는 수동 재설정 이벤트 CreateEvent입니다. msdn.microsoft.com/en-us/library/ms686364%28VS.85%29.aspx
ChaosPandion

1
@Zwei-글쎄, 그것이 무엇이든간에 이것이 내가 Java 전문가 였다면 게시했을 답변입니다.
ChaosPandion

15

적어도 단일 코어 컴퓨터에서는 불가능합니다. 하지만 왜 그걸 원합니까? 정확히 같은 시간에 두 개의 스레드를 시작할 수 있더라도 스케줄링이 제어되지 않기 때문에 서로 다르게 진행됩니다.

편집 : (일부 의견에 대한 응답으로) 여러 스레드 의 상태 또는 진행 상황동기화하는 것은 완벽하게 유효한 요구 사항 CyclicBarrier이며 훌륭한 도구입니다. 정확히 동시에 여러 스레드를 시작할 수 있는지 여부에 대한 질문에 대답했습니다 . CyclicBarrier스레드가 정확히 원하는 상태에있을 때 스레드가 진행되도록 보장 하지만 거의 비슷할 수도 있지만 정확히 동시에 시작하거나 다시 시작할 것이라는 보장은 없습니다 . 질문에 동기화 요구에 대한 언급이 없습니다.


1
그래도 꽤 가까이 다가 갈 수 있습니다. 그것은 모두 당신이 사용하는 동기화 기술 과 물론 1 개 이상의 CPU 또는 코어를 갖는 것에
ChaosPandion

아이디어는 이것이 잘못된 접근 방식이며 하드 실시간이 아닌 환경에서는 필요하지 않으며 "매우 가깝다"는 것이 아닙니다.
Nikolai Fetissov

1
그것은이다 또한 자바 쓰레드 스케줄링 당신에게 밀리 초 정확성을 제공하지 않기 때문에 불가능합니다.
Stephen C

1
@Zwei-유휴 상태 인 컴퓨터에서 대부분의 경우 "젠장 가까이"를 할 수 있습니다. 그러나 항상 필요한 경우 OS에서 실시간 지원이 가능한 컴퓨터에서 C와 같은 언어로 프로그래밍해야합니다. 또한 JVM이 스레드를 시작하려는 "분할 초"에 전체 GC를 실행할 수 있음을 고려하십시오.
Stephen C

1
완벽하게 유효한 동기화 문제입니다. 스레드는 일부 데이터를 초기화해야하며 적절한 유효성 검사 없이는 중요한 영역에 들어 가지 않도록해야합니다. 그리고 CyclicBerrier가 javas 동시 패키지에 포함되어 있다는 사실은 이것이 중요한 문제임을 의미합니다.
Denis Tulskiy

14

이를 위해 CountDownLatch를 사용할 수 있습니다. 아래에서 샘플을 찾으십시오. t1 및 t2가 시작되었지만이 스레드는 주 스레드가 래치를 카운트 다운 할 때까지 계속 대기합니다. 필요한 카운트 다운 수는 생성자에 언급되어 있습니다. 카운트 다운 래치를 사용하여 스레드 실행이 완료 될 때까지 대기하여 주 스레드가 더 진행될 수 있도록 할 수도 있습니다 (반대 경우). 이 클래스는 Java 1.5부터 포함되었습니다.

import java.util.concurrent.CountDownLatch;


public class ThreadExample
{
    public static void main(String[] args) 
    {
        CountDownLatch latch = new CountDownLatch(1);
        MyThread t1 = new MyThread(latch);
        MyThread t2 = new MyThread(latch);
        new Thread(t1).start();
        new Thread(t2).start();
        //Do whatever you want
        latch.countDown();          //This will inform all the threads to start
        //Continue to do whatever
    }
}

class MyThread implements Runnable
{
    CountDownLatch latch;
    public MyThread(CountDownLatch latch) 
    {
        this.latch = latch;
    }
    @Override
    public void run() 
    {
        try 
        {
            latch.await();          //The thread keeps waiting till it is informed
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //Do the actual thing
    }
}

이 답변은 코드 예제에서 더 적은 상용구에서 도움이 될 수 있습니다.
user2418306 2016-04-02

6
  1. 내가 이해하는 것처럼 JVM은 대부분이 작업을 운영 체제에 위임합니다. 따라서 대답은 OS에 따라 다릅니다.
  2. 단일 프로세서 시스템에서는 불가능합니다.
  3. 다중 프로세서 시스템과 관련하여 더 복잡합니다. 동시성의 상대성 이론에 따르면 , "두 사건이 공간에서 분리되어 있다면 두 사건이 동시에 발생하는지 절대적인 의미로 말할 수 없다." 프로세서가 아무리 가까이 있더라도 공간에서 분리됩니다.
    1. 상대적인 동시성을 받아 들일 수 있다면 다른 응답에서 논의 된 기술을 사용하여 시뮬레이션하는 것이 더 쉬울 것입니다.

1
… 동시 시작을 가정하더라도 각 스레드는 고유 한 타임 라인을 가지고 있으며 모두 동시 적이지만 반드시 병렬은 아닙니다. 따라서 누군가가 스레드의 동시성에 대해 가정하는 모든 것이 다음 나노초 (둘 중 어느 쪽이든) 동안 무효화 될 수 있습니다. 타임 라인)…
Holger
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.