조회 수 14701 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print

http://csharpstudy.com/Threads/autoresetevent.aspx

 

신호(Signal)에 의한 쓰레드 동기화

쓰레드 동기화에는 Locking과 같이 공유 리소스에 락을 걸어 쓰레드 접근을 제한하는 방식 (Monitor, Mutex, Semaphore 등)이외에 대기 중인 쓰레드에게 외부에서 신호(Signal)을 보냄으로써 쓰레드 흐름을 통제하는 방식도 있다. 이러한 신호(Signaling) 방식으로 많이 사용되는 것으로 AutoResetEvent, ManualResetEvent, CountdownEvent, Wait/Pulse 등이 있다. (NOTE: 여기서의 Event는 윈도우 프로그래밍에서 말하는 이벤트와 전혀 다른 개념이다. 여기서의 Event는 쓰레드 동기화에 사용되는 OS 리소스이다)




AutoResetEvent 클래스

AutoResetEvent는 이 이벤트를 기다리는 쓰레드들에게 신호를 보내 하나의 쓰레드만 통과시키고 나머지 쓰레드들은 다음 신호를 기다리게 한다. 이는 흡사 유료 주차장 자동 게이트와 같이 한 차량이 통과하면 자동으로 게이트가 닫히는 것과 같다. 쓰레드 A가 AutoResetEvent 객체의 WaitOne() 메소드를 써서 대기하고 있다가, 다른 쓰레드 B에서 이 AutoResetEvent 객체의 Set() 메서드를 호출하면, 쓰레드 A는 대기 상태를 해제하고 계속 다음 문장을 실행할 수 있게 된다.

예제

using System;
using System.Threading;

namespace MultiThrdApp
{
    class Program
    {
        // AutoResetEvent 객체 필드
        static AutoResetEvent autoEvent = new AutoResetEvent(false);

        static void Main()
        {
            // 쓰레드 A 생성
            Thread A = new Thread(Run);
            A.Name = "Thread A";
            A.Start();            

            // 메인쓰레드            
            Thread.Sleep(3000); //3초 대기
            autoEvent.Set(); // 쓰레드 A에 신호
        }

        static void Run()
        {
            string name = Thread.CurrentThread.Name;
            Console.WriteLine("{0}: Run Start", name);

            // AutoResetEvent 신호 대기
            autoEvent.WaitOne();            
            Console.WriteLine("{0} : DoWork", name);

            Console.WriteLine("{0}: Run End", name);
        }
    }
}



AutoResetEvent 활용 예제

AutoResetEvent 활용한 한 예제로 교통 신호를 통제하는 예를 들어 보자. 실제 교통 신호보다 좀 단순화하여 상하방향과 좌우방향만을 각각 통제하는 2개의 신호만이 있다고 가정하자. 상하방향 신호가 켜지면 상하방향 차량들이 모두 통과되고 (즉, 상하방향 Queue에 있는 모두 데이타 처리), 더 이상 차량이 없으면 좌우방향에 신호를 보내 좌우방향에 밀려 있는 차량들을 통과한다 (즉, 좌우방향 Queue에 있는 모두 데이타 처리). 아래 예제는 2개의 쓰레드가 각각 상하, 좌우 데이타 처리를 위한 메서드들을 실행하고, 2개의 AutoResetEvent 객체를 신호로 사용하고 있다. 각 쓰레드의 메서드는 먼저 자신의 신호 이벤트를 기다렸다가 이벤트가 Set되면 큐의 있는 모든 데이타를 처리한 후 상대편 이벤트를 Set하여 상대편에게 실행 제어권을 넘긴다. 메인쓰레드에서는 계속 데이타를 큐에 넣는 역활을 하고 있다.

예제

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

namespace MultiThrdApp
{
    class Program
    {
        static void Main()
        {
            Traffic traffic = new Traffic();

            // 2개의 쓰레드 구동
            Thread v = new Thread(traffic.ProcessVertical);
            Thread h = new Thread(traffic.ProcessHorizontal);
            v.Start();
            h.Start();

            // 메인쓰레드에서 데이타 전송
            for (int i = 0; i < 30; i+=3)
            {
                traffic.AddVertical(new int[] { i, i + 1, i + 2 });
                traffic.AddHorizontal(new int[] { i, i + 1, i + 2 });
                Thread.Sleep(10);
            }

            Thread.Sleep(1000);
            traffic.Running = false;                 
        }
    }

    class Traffic
    {
        private bool _running = true;

        // 상하, 좌우 통행 신호 역활을 하는 AutoResetEvent 이벤트들
        private AutoResetEvent _evtVert = new AutoResetEvent(true);
        private AutoResetEvent _evtHoriz = new AutoResetEvent(false);

        private Queue<int> _Qvert = new Queue<int>();
        private Queue<int> _Qhoriz = new Queue<int>();

        // 상하방향의 큐 데이타 처리
        // Vertical 방향의 처리 신호(_evtVert)를 받으면
        // Vertical 큐의 모든 큐 아이템을 처리하고
        // 좌우방향 처리 신호(_evtHoriz)를 보냄
        public void ProcessVertical()
        {            
            while (_running)
            {
                // Vertical 방향 처리 신호 기다림
                _evtVert.WaitOne();

                // Vertical 큐의 모든 데이타 처리
                // 큐는 다른 쓰레드에서 엑세스 가능하므로 lock을 건다
                lock (_Qvert)
                {
                    while (_Qvert.Count > 0)
                    {
                        int val = _Qvert.Dequeue();
                        Console.WriteLine("Vertical : {0}", val);
                    }
                }

                // Horizontal 방향 처리 신호 보냄
                _evtHoriz.Set();
            }

            Console.WriteLine("ProcessVertical : Done");
        }

        // 좌우방향의 큐 데이타 처리
        // Horizontal 방향의 처리 신호(_evtHoriz)를 받으면
        // Horizontal 큐의 모든 큐 아이템을 처리하고
        // 상하방향 처리 신호(_evtHoriz)를 보냄
        public void ProcessHorizontal()
        {
            while (_running)
            {
                _evtHoriz.WaitOne();

                lock (_Qhoriz)
                {
                    while (_Qhoriz.Count > 0)
                    {
                        int val = _Qhoriz.Dequeue();
                        Console.WriteLine("Horizontal : {0}", val);
                    }
                }
                
                _evtVert.Set();
            }

            Console.WriteLine("ProcessHorizontal : Done");
        }

        public bool Running
        {
            get { return _running; }
            set { _running = value; }
        }

        public void AddVertical(int[] data)
        {
            lock (_Qvert)
            {
                foreach (var item in data)
                {
                    _Qvert.Enqueue(item);
                }                
            }
        }

        public void AddHorizontal(int[] data)
        {
            lock (_Qhoriz)
            {
                foreach (var item in data)
                {
                    _Qhoriz.Enqueue(item);    
                }                
            }
        }
    }
}

Dreamy의 코드 스크랩

내가 모으고 내가 보는

List of Articles
번호 분류 제목 날짜 조회 수 추천 수
461 C# ArrayList를 string[] 배열로 변환하는 방법 2015.09.23 12895 0
460 Android ART(Android RunTime)에 대해 1 2014.02.10 16117 0
459 Pi ATTINY85 PIN정보, Data sheet 2 file 2016.12.10 8984 0
» C# AutoResetEvent 클래스 - 신호(Signal)에 의한 쓰레드 동기화 2013.08.14 14701 0
457 LINUX awk 명령어 사용법 1 2006.02.16 114637 15
456 업무 Back-End 관련 정보 2022.05.17 1450 0
455 C Base64 로 encoding / decoding 하는 예제 file 2005.09.22 25875 0
454 LINUX bash 의 명령어 History 2015.01.20 7312 0
453 일반 bat(배치) 파일 제대로 쓰기 2009.02.24 53960 0
452 Python BeautifulSoup로 HTML 파싱 끝내기 2013.04.08 42534 0
451 Python BeautifulSoup으로 웹에 있는 데이터 긁어오기 2013.04.08 76934 0
450 C# Best way to implement keyboard shortcuts in a Windows Forms application 2015.11.06 6644 0
449 일반 Beyond Compare로 patch 파일 만들기, 적용하기 file 2012.10.22 16303 0
448 LINUX bluetooth on Ubuntu 2017.05.25 13464 0
447 일반 BT와 BLE 2017.05.16 6532 0
목록
Board Pagination ‹ Prev 1 2 3 4 5 6 7 8 9 10 ... 34 Next ›
/ 34

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5