[java] 두 개의 스레드를 “정확히”동시에 시작하는 방법

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

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



답변

스레드를 정확히 동시에 시작하려면 (최소한 가능한 한 좋게) 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에서 정확히 동시에 시작 되는지 확인할 수는 없지만 거의 비슷할 수 있습니다. 예를 들어 성능 테스트를 수행 할 때 꽤 가까워지는 것이 여전히 유용합니다. 예를 들어 서로 다른 수의 스레드를 사용하여 데이터 구조의 처리량을 측정하려는 경우 이러한 종류의 구조를 사용하여 가능한 가장 정확한 결과를 얻으려고합니다.

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


답변

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

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


답변

이를 위해 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
    }
}


답변

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


답변