Let's Girin!

[Unity] DOTS - Job 시스템 본문

Unity

[Unity] DOTS - Job 시스템

window= 2026. 6. 25. 19:57

1. 멀티스레드 환경에서의 C# 잡 시스템

🔹잡 시스템의 기본 개념

Unity에서 게임 로직은 주로 MonoBehaviour의 업데이트 함수에서 실행되는데, 이 업데이트 함수는 메인 스레드에서만 실행된다. 그러나 멀티코어 CPU 환경에서는 하나의 코어에서만 모든 작업을 처리하는 것이 비효율적이기 때문에, 여러 코어를 활용하려면 멀티스레딩을 사용해야 한다. C# 잡 시스템은 멀티스레드 환경에서 게임 로직을 더 효율적으로 실행하도록 설계된 기능이다.

 

  • 워커 스레드: 잡 시스템은 플랫폼의 CPU 코어 수에 맞춰 워커 스레드를 생성한다. 예를 들어, 8개의 CPU 코어가 있다면, 1개의 메인 스레드 외에 7개의 워커 스레드가 생성된다.
  • : 각 워커 스레드는 '잡'이라는 단위의 작업을 실행한다. 잡은 대기열에서 실행할 작업을 가져와 실행하며, 작업을 끝낼 때까지 다른 작업을 처리하지 않는다.
  • 중단 없는 실행: 잡은 실행이 시작되면, 완료될 때까지 중단 없이 실행된다. 이는 작업의 일관성을 유지하고, 작업 중간에 상태 변경이 발생하지 않도록 보장한다.

 

🔹멀티스레딩과 동기

C# 잡 시스템은 멀티스레딩 환경에서 동기화 동시성을 처리하는데 중요한 역할을 한다. 게임 로직을 여러 스레드에서 실행하는 경우, 데이터가 동시에 접근되거나 수정되는 일이 발생할 수 있는데, 이를 방지하려면 여러 가지 방법을 사용해야 한다.

 

  • 동기화: 여러 스레드가 동시에 실행되면서 발생할 수 있는 데이터 손상을 방지하려면, 잡 시스템은 스레드 간 안전성 검사 및 동기화 처리를 제공한다.
  • 경쟁 상태 방지: 두 개 이상의 스레드가 동일한 데이터를 동시에 수정하려는 상황을 경쟁 상태라고 한다. C# 잡 시스템은 이러한 경쟁 상태를 예방하기 위해, 잡 간의 데이터 격리 및 안전성 검사 기능을 제공한다.

 

2. 잡 스케줄링 및 완료

C# 잡 시스템에서 잡은 메인 스레드에서만 스케줄링할 수 있다. 즉, 다른 스레드나 잡이 새로운 잡을 스케줄하는 것은 불가능하다. 이를 통해 잡 시스템은 복잡한 멀티스레드 환경에서도 안정성을 유지한다.

 

🔹Complete() 메서드

잡이 실행되고 나서, 메인 스레드는 Complete() 메서드를 사용하여 해당 잡이 완료될 때까지 기다릴 수 있다. 이 메서드는 메인 스레드에서만 호출할 수 있으며, 호출된 후에는 해당 잡이 완료될 때까지 대기한다.

 

  • 메인 스레드에서 호출: Complete() 메서드는 오직 메인 스레드에서만 호출될 수 있다. 메인 스레드가 호출한 후, 해당 잡은 완료될 때까지 대기한다.
  • 데이터 안전성 보장: Complete() 메서드가 반환되면, 해당 잡에서 사용된 데이터는 메인 스레드에서 안전하게 액세스할 수 있다. 이렇게 함으로써 다른 스레드와의 데이터 충돌을 예방하고, 데이터의 일관성을 유지할 수 있다.

 

* Job 구조체 정의

// IJob 인터페이스를 구현하여 잡 정의.
using Unity.Collections;
using Unity.Jobs;

[BurstCompile]
public struct MyCalculationJob : IJob
{
    // NativeArray: 워커 스레드와 안전하게 공유되는 데이터.
    public NativeArray<float> results;
    public float multiplier;

    public void Execute()
    {
        // 워커 스레드에서 실행되는 로직.
        for (int i = 0; i < results.Length; i++)
        {
            results[i] = results[i] * multiplier;
        }
    }
}

 

* 메인 스레드에서 잡 스케줄링

public class JobSchedulerExample : MonoBehaviour
{
    private void Update()
    {
        // NativeArray 생성 (Allocator.TempJob: 잡 실행 동안만 유지).
        var results = new NativeArray<float>(1000, Allocator.TempJob);

        // 초기값 설정.
        for (int i = 0; i < results.Length; i++)
            results[i] = i;

        // 잡 인스턴스 생성 — 메인 스레드에서만 가능.
        var job = new MyCalculationJob
        {
            results    = results,
            multiplier = 2.5f
        };

        // Schedule(): 잡을 대기열에 등록하고 JobHandle을 반환.
        JobHandle handle = job.Schedule();

        // Complete() 호출 전까지 메인 스레드는 다른 작업 가능.
        DoOtherWork();

        // Complete(): 잡이 끝날 때까지 메인 스레드 대기.
        handle.Complete();

        // Complete() 반환 후 — 데이터 안전하게 읽기 가능.
        float firstResult = results[0];
        Debug.Log($"결과: {firstResult}");

        // NativeArray는 반드시 수동으로 해제.
        results.Dispose();
    }

    private void DoOtherWork()
    {
        // 잡 실행 중 메인 스레드가 처리할 수 있는 작업들.
        Debug.Log("잡 실행 중 — 메인 스레드는 자유롭게 동작 가능 !!");
    }
}

 

* 잡 의존성 연결

// 여러 잡을 순서대로 실행: JobA 완료 → JobB 실행.
JobHandle handleA = jobA.Schedule();

// handleA를 dependency로 전달 → JobA가 끝난 뒤 JobB 시작.
JobHandle handleB = jobB.Schedule(handleA);

// 여러 잡을 한 번에 기다릴 때.
JobHandle combined = JobHandle.CombineDependencies(handleA, handleB);
combined.Complete();

// 모든 잡이 완료된 후 데이터 접근 가능.
dataArray.Dispose();

 

3. 안전성 검사 및 종속성 관리

멀티스레드 환경에서 가장 중요한 문제는 스레드 간 안전성을 보장하는 것이다. 특히 여러 스레드가 동일한 데이터를 수정할 때 충돌이 발생할 수 있다. C# 잡 시스템은 이러한 문제를 방지하는 안전성 검사 기능을 제공한다.

 

🔹데이터 격리

잡 시스템은 데이터 격리를 보장하여, 각 잡이 자신만의 데이터를 사용하게 한다. 이를 통해 다른 잡이나 메인 스레드에서 데이터를 변경하는 것을 방지한다.

🔹경쟁 상태 방지

동일한 데이터에 여러 잡이 동시에 접근하려고 할 때, 경쟁 상태가 발생할 수 있다. 예를 들어, 두 개의 잡이 동일한 배열에 데이터를 쓸 때 충돌이 발생할 수 있다. 이를 방지하기 위해 C# 잡 시스템은 경쟁 상태 검사 동기화를 자동으로 처리한다.

🔹잡 간의 종속성 관리

잡 간의 종속성도 매우 중요하다. 잡이 다른 잡에 의존하는 경우, 의존 관계를 명확하게 정의하여 충돌을 방지할 수 있다.

  • 잡 종속성: 예를 들어, A 잡이 완료되어야만 B 잡이 실행될 수 있도록 할 수 있다. 이를 통해 A 잡과 B 잡이 동일한 데이터에 접근하는 경우 충돌을 방지할 수 있다.

🔹잡 간 안전성 예시

A 잡과 B 잡이 동일한 배열을 공유하는 경우, B 잡은 A 잡이 완료될 때까지 실행되지 않도록 설정할 수 있다. 이를 통해 두 잡이 동시에 실행되면서 데이터를 수정하는 상황을 방지할 수 있다.

 

4. 주의사항 : I/O 작업에 대한 제약

C# 잡 시스템은 CPU 작업을 최적화하기 위한 도구로 설계되었다. 입출력(I/O) 작업은 CPU 작업과는 다르게 처리해야 한다. 예를 들어 파일 읽기/쓰기나 네트워크 통신 같은 작업은 I/O 작업에 해당하며, 이러한 작업은 메인 스레드에서 비동기 API를 사용하여 처리해야 한다.

  • I/O 작업을 잡에서 처리하지 말 것: I/O 작업을 잡에서 수행하면, CPU 코어를 최적화하려는 목적에 맞지 않으며, I/O 작업이 차단(blocking)되면 전체 CPU 성능이 저하될 수 있다.

 

 

 

** 결론

  • C# 잡 시스템은 멀티스레드 환경에서 게임 로직을 효율적으로 실행하고, CPU 코어를 최적화하는 데 매우 유용한 도구이다. 이 시스템을 사용하면 멀티코어 환경에서 더 나은 성능을 발휘할 수 있으며, 잡 간의 종속성 및 안전성을 관리하여 데이터 충돌을 방지할 수 있다.
  • C# 잡 시스템을 사용한 멀티스레딩 프로그래밍을 통해 복잡한 동시성 문제를 효율적으로 처리할 수 있으며, 게임 개발에서 성능을 극대화할 수 있다.

◈ 유니티 공식 문서를 참고하여 작성하였습니다◈

반응형

'Unity' 카테고리의 다른 글

[Unity] DOTS - Entities  (0) 2026.06.27
[Unity] DOTS - Collections 및 Mathematics  (0) 2026.06.26
[Unity] DOTS - Burst Compiler  (0) 2026.06.25
[Unity ] DOTS - DOTS가 필요한 이유  (0) 2026.06.23
[Unity] DOTS - 메모리 및 CPU 캐시  (0) 2026.06.22