Unity3D/C#

C# 강좌 Day-25 스레드

일등하이 2021. 9. 7. 13:55
반응형

Process : 실행파일이 실행되어 메모리에 적재된 인스턴스
Thread : 프로세스내에서 실행되는 흐름의 단위

 

각 프로세스는 주 스레드라고 하는 단일 스레드로 시작한다.
모든 스레드에서 추가 스레드를 만들수 있다
프로세스 내의 모든 스레드는 해당 프로세스의 주소 공간을 공유 한다

 

https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

 

https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

 

메인 메서드의 코드는 순차적으로 실행된다 하지만 메서드에서 또 다른 메서드 단위로 프로그램을 작성해놓고 이를 스레드 개체로 실행 하면 메서더의 실행 순서를 운영체제에 맡길수 있다 그러면 순차적으로 실행되지 않고 반복적으로 여러 메서드를 나누어 처리 한다 스레드는 순차적으로 처리 되지 않고 여러 기능을 동시다발적으로 실행할대 사용하는 개념이며 닷넷에서는 Thread 클래스를 제공한다 

 

<프로세스와 스레드>

 

스레드를 현실세계에 비유하자면 작업자 한명을 의미한다 

집에서 혼자 아침 식사를 준비해야 한다면 한 명 (스레드)만 있어도 충분 하겠지만 

큰 식당에서는 여러명 (스레드)가 있어야 많은 양의 요리를 준비 할수 있다 

※ 여러 스레드를 사용해 일을 진행하는 방식을 병렬(Parallel) 프로그래밍이라고 한다 

 

 

 

 

1. 네임스페이스 정의 

System.Threading

 

2. 스레드를 사용해 실행할 메서드정의 

void SayHello()
{
    Console.WriteLine("hello world!");
}

 

 

3. ThreadStart대리자 인스턴스화 

ThreadStart ts = new ThreadStart(this.SayHello);

 

4. Thread 변수 선언

Thread t;

 

5. Thread 인스턴스화 (매개변수로 ThreadStart인스턴스 할당)

t = new Thread(ts);

 

 

6. 스레드 인스턴스 메서드 Start() 호출 

t.Start();

 

 

 

[전체코드]

using System;
using System.Threading;
class App
{
    public App()
    {
        Thread t;

        ThreadStart ts = new ThreadStart(this.SayHello);
        t = new Thread(ts);
        t.Start();
    }

    void SayHello()
    {
        Console.WriteLine("hello world!");
    }
}

 

Thread 클래스의 주요 맴버 

Priority 스레드의 예약 우선 순위를 나타내는 값을 가져오거나 설정합니다.
Abort() 메서드가 호출되는 스레드에서 ThreadAbortException 발생시켜 스레드 종료 프로세스를 시작합니다 메서드를 호출하면 대개 스레드가 종료됩니다.
Sleep() 지정된 시간 동안 현재 스레드를 일시 중단합니다.
Join() 인스턴스가 나타내는 스레드가 종료될 때까지 호출 스레드를 차단합니다
Start() 스레드의 실행 일정을 예약합니다.

 

lock 문은 지정된 개체에 대한 상호 배제 잠금을 획득하여 명령문 블록을 실행한 다음, 잠금을 해제합니다. 잠금이 유지되는 동안 잠금을 보유하는 스레드는 잠금을 다시 획득하고 해제할 있습니다. 다른 스레드는 잠금을 획득할 없도록 차단되며 잠금이 해제될 때까지 대기합니다.

 

 

다음 예제는 여러배럭스에서 마린을 동시에 생산하는것을 가정했다

using System;
using System.Threading;

namespace HelloWorld
{
    public class Marine { }

    public class Barracks
    {
        public Barracks()
        {
        }
        public void CreateMarine(object callback) {
            for (int i = 0; i < 10; i++) {
                Thread.Sleep(100);
            }

            (callback as Action<Marine>)(new Marine());
        }
    }
}
using System;
using System.Collections.Generic;
using System.Threading;

namespace HelloWorld
{
    public class App
    {
        public App()
        {
            List<Barracks> list = new List<Barracks>();
            object lockobj = new object();

            for (int i = 0; i < 10; i++) {
                list.Add(new Barracks());
            }

            List<Marine> marines = new List<Marine>();
            Action<Marine> action = (marine) => {
                lock (lockobj)
                {
                    marines.Add(marine);
                }
            };
            List<Thread> threads = new List<Thread>();
            foreach(Barracks b in list)
            {
                var t = new Thread(new ParameterizedThreadStart(b.CreateMarine));
                threads.Add(t);
                t.Start(action);
            }
            foreach (Thread t in threads) {
                t.Join();
            }

            Console.WriteLine(marines.Count);
            
        }
    }
}

 

 

다음 예제는 여러마리의 SCV가 동시에 미네랄을 채취하는 경우를 가정했다 

 lockobj(열쇠)를 하나만 만들어 모든 SCV에게 건내주어 한 스레드에서 공유 자원을 접근할때 다른 스레드에서 접근 못하게 했다

using System;
using System.Collections.Generic;
using System.Threading;

namespace HelloWorld
{
    public class Minerals {
        private int amount = 100;

        public int Amount {
            get {
                return this.amount;
            }
            set {
                this.amount = value;
            }
        }
    }

    public class App
    {
        private Minerals minerals = new Minerals();
        private object lockobj = new object();

        public App()
        {
            List<SCV> list = new List<SCV>();
            for (int i = 0; i < 10; i++) {
                SCV scv = new SCV(i, minerals, lockobj);
                list.Add(scv);
            }

            List<Thread> threads = new List<Thread>();

            foreach (SCV scv in list) {
                Thread t = new Thread(scv.Work);
                t.Start();
                threads.Add(t);
            }
            foreach (var t in threads)
            {
                t.Join();
            }

            Console.WriteLine("minerals: {0}", this.minerals.Amount);

        }
    }
}
using System;
using System.Collections.Generic;
using System.Threading;

namespace HelloWorld
{
    public class Minerals {
        private int amount = 100;

        public int Amount {
            get {
                return this.amount;
            }
            set {
                this.amount = value;
            }
        }
    }

    public class App
    {
        private Minerals minerals = new Minerals();
        private object lockobj = new object();

        public App()
        {
            List<SCV> list = new List<SCV>();
            for (int i = 0; i < 10; i++) {
                SCV scv = new SCV(i, minerals, lockobj);
                list.Add(scv);
            }

            List<Thread> threads = new List<Thread>();

            foreach (SCV scv in list) {
                Thread t = new Thread(scv.Work);
                t.Start();
                threads.Add(t);
            }
            foreach (var t in threads)
            {
                t.Join();
            }

            Console.WriteLine("minerals: {0}", this.minerals.Amount);

        }
    }
}

.NET의 Thread 클래스를 이용하여 쓰레드를 하나씩 만들어 사용하는 것이 아니라, 이미 존재하는 쓰레드 풀에서 사용 가능한 작업 쓰레드를 할당 받아 사용하는 방식이 있는데, 이는 다수의 쓰레드를 계속 만들어 사용하는 것보다 효율적이다.

using System;
using System.Collections.Generic;
using System.Threading;

namespace HelloWorld
{

    public class App
    {
        public App()
        {
            Console.WriteLine("App");
            ThreadPool.QueueUserWorkItem(SayHello); 
            ThreadPool.QueueUserWorkItem(SayHello, "Hello"); 
            ThreadPool.QueueUserWorkItem(SayHello, "World!");
        }

        void SayHello(object message)
        {
            Console.WriteLine("message: {0}", message.ToString());
        }
    }
}

 

 

 

참고:

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4

https://ko.wikipedia.org/wiki/%EC%8A%A4%EB%A0%88%EB%93%9C_(%EC%BB%B4%ED%93%A8%ED%8C%85) 

https://docs.microsoft.com/ko-kr/dotnet/api/system.threading.thread?view=net-5.0 

https://docs.microsoft.com/ko-kr/dotnet/api/system.threading.threadstart?view=net-5.0 

https://www.sysnet.pe.kr/2/0/986

https://www.csharpstudy.com/Threads/threadpool.aspx

https://nowonbun.tistory.com/136

https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

 

반응형