티스토리 뷰

IT지식

Unity Thread 사용하기

민자르 2018. 6. 28. 11:36
반응형

Thread 란?


여기서는 전문적인 내용이 아닌 심플하게 사용하는 방법만 언급하겠습니다.

하나의 프로그램 내에서 여러개의 실행 흐름을 두기 위한 모델입니다. 흠.. 설명이 좀 쉽지 않네요. 쉽게 말하면 동시에 여러 일을 처리하는 것 입니다.


예를 들어서


int n = 0;

for (int i=0;i<10000;i++)

{

n += i + 1;

}


printf( "sum : %d", n);


1 ~ 10000 까지 더하는 소스입니다. 저 소스에서 for 문에 진입해서 빠져 나오기까지 프로그램은 먹통같은 느낌이 됩니다. 만일 실수로 for문을 잘 못 적으면 무한루프에 빠지게 된다.


for (int i=0;i<10000;i--)

 

무한 루프에 빠지는 코딩이다


쓰레드를 사용하면 먹통되는 느낌을 막을 수 있습니다. 하지만 먹통되는 코딩을 하면 안되겠지요. 버그 발생은 시키지 맙시다.


컴퓨터에서 프로그램을 실행하게 되면 cpu에서 프로세스를 생성합니다. 프로세스를 동시에 여러개 처리 할 수 있는 기능이 쓰레드입니다. 쓰레드는 프로세서가 프로세스 작업을 처리하기 위해 할당 한 프로세스 수행 시간을 쪼개서 여러개의 작업을 수행 할 수 있도록 만든 방법입니다. 그리고 쓰레드는 여러 개념이 있는데 여기서는 간단하게 사용할 수 있는 중심으로 한 예를 들어서 하겠습니다.



class ExThread
{
    void init()
    {
        // 파라미터 없는 ThreadStart 사용
        Thread t1 = new Thread(new ThreadStart(Run));
        t1.Start();

        // ParameterizedThreadStart 파라미터 전달
        // Start()의 파라미터로 radius 전달
        Thread t2 = new Thread(new ParameterizedThreadStart(Calc));
        t2.Start(10.00);

        // ThreadStart에서 파라미터 전달
        Thread t3 = new Thread(() => Sum(10, 20, 30));
        t3.Start();
    }

    void Run()
    {
        Console.WriteLine("Run");
    }

    // radius라는 파라미터를 object 타입으로 받아들임
    void Calc(object radius)
    {
        double r = (double)radius;
        double area = r * r * 3.14;
        Console.WriteLine("r={0},area={1}", r, area);
    }

    void Sum(int d1, int d2, int d3)
    {
        int sum = d1 + d2 + d3;
        Console.WriteLine(sum);
    }
}



위 소스가 쓰레드를 사용하는 예제입니다. 여기서 사용하는 예제에서 중요하게 봐야 하는 것은 파라미터 유무에 따라서 코딩이 달라지는 것입니다. 파라미터가 전달 하는 방법은 두가지 방법이 있는데 둘 중 아무거나 처리하면 됩니다. 


그리고 꼭 기억해야 할 함수가 있습니다. Start() Join() Abort() 세가지만 기억합시다. 시작이고 대기이고 강제종료입니다. Start()만 기억하면 문제 될 것이 없습니다.


Thread 를 사용하면 임계영력 개념도 알아서 Lock 처리를 해야 하지만 그건 따로 찾아 보시면 됩니다.



C#에서 Thread 를 하다 보면 에러를 보게 됩니다. Main Thread 가 아닌 곳에서 File 읽기나 UI 처리를 하려고 하면 에러가 생깁니다. 만일 처리하고자 한다면 쓰레드에서 변수에 담아 두시고 Main에서 읽어서 처리하면 됩니다. 이럴때  Lock 처리가 필요합니다.


class MyClass 
{ 
    private int counter = 0; 
    public void Run() 
    { 
        // 10개의 스레드가 동일 메서드 실행 
        for (int i = 0; i < 10; i++) 
        { 
            new Thread(UnsafeCalc).Start(); 
        } 
    } 
    // Thread-Safe하지 않은 메서드 
    private void UnsafeCalc() 
    { 
        // 객체 필드를 모든 스레드가 자유롭게 변경 
        counter++; 
        // 가정 : 다른 복잡한 일을 한다 
        for (int i = 0; i < 10000; i++) 
            for (int j = 0; j < 10000; j++); 
        // 필드값 읽기 
        Console.WriteLine(counter); 
    } 
}


위와 같이 코딩하면 원하지 않는 결과를 초래할 수 있습니다. 그래서 아래와 같이 수정이 필요합니다.


class MyClass 
{ 
    private int counter = 0; 
    // lock문에 사용될 객체 
    private object lockObject = new object(); 
    public void Run() 
    { 
        // 10개의 스레드가 동일 메서드 실행 
        for (int i = 0; i < 10; i++) 
        { 
            new Thread(SafeCalc).Start(); 
        } 
    } 
    // Thread-Safe 메서드 
    private void SafeCalc() 
    { 
        // 한번에 한 스레드만 lock블럭 실행 
        lock (lockObject) 
        { 
            // 필드값 변경 
            counter++; 
            // 가정 : 다른 복잡한 일을 한다 
            for (int i = 0; i < 10000; i++) 
                for (int j = 0; j < 10000; j++); 
            // 필드값 읽기 
            Console.WriteLine(counter); 
        } 
    } 
}


lock 반드시 사용해야 합니다. 그리고  mutex 나 semaphore 가 있는데 이 내용도 많으니 찾아서 알아두시면 됩니다. 쓰레드는 책 한권 정도의 분량이 될 만큼 개념과 상황별 어떻게 적용할지가 많으니 깊이 공부하고 싶으면 찾아서 보시면 됩니다.

728x90
반응형
댓글