C#/수업 내용

[C#] thread, lock

JSH1 2021. 9. 12. 03:21

프로세스는 실행 중인 프로그램
스레드는 운영 체제가 프로세서 시간을 할당하는 기본 단위

        public App()
        {
            ThreadStart ts = new ThreadStart(Work); // 대리자
            Thread t = new Thread(ts);

            Console.WriteLine(t.ThreadState); // Unstarted

            t.Start(); // Unstarted -> Running

            t.Join(); // thread가 하는 일이 끝날때까지 대기
            Console.WriteLine(t.ThreadState); //  Stopped
            
        }

        // 작업 스레드에서 동작할 메서드 정의
        void Work()
        {
            for(int i=0; i<10; i++)
            {
                Console.WriteLine(i);
                Thread.Sleep(1000);
            }
        }


    using System;
    using System.Threading;
    using System.Diagnostics;

    class Counter
    {
        public int count = 0;

        public void AddCount()
        {
            for (int i = 0; i < 10; i++)
            {
                    this.count += 1;
                    Thread.Sleep(100);
                    Console.WriteLine("{0}: {1}", Thread.CurrentThread.ManagedThreadId, count);
            }
        }
    }

    class App
    {
        public App()
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            Counter c = new Counter();

            Thread thread1 = new Thread(c.AddCount);
            Thread thread2 = new Thread(c.AddCount);

            thread1.Start();
            thread2.Start();


            thread1.Join();
            thread2.Join();


            Console.WriteLine("count: {0}", c.count);

            stopwatch.Stop();
            Console.WriteLine("{0} ms", stopwatch.ElapsedMilliseconds);
        }
    }

보통 코드가 순차적으로 실행이 돼서 count 값이 1~20 순으로 차례대로 올라갈 거라 생각했지만
첫 번째 스레드에서 count 값을 1로 올려주고 0.1초 대기하고 출력할때
두 번째 스레드에서 count값이 2로 변경되면서 1이 아닌 2가 출력되었다


    using System;
    using System.Threading;
    using System.Diagnostics;

    class Counter
    {
        public int count = 0;
        private readonly object thisLock = new object();

        public void AddCount()
        {
            for (int i = 0; i < 10; i++)
            {
                lock (thisLock)
                {
                    this.count += 1;
                    Thread.Sleep(100);
                    Console.WriteLine("{0}: {1}", Thread.CurrentThread.ManagedThreadId, count);
                }
            }
        }
    }

    class App
    {
        public App()
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            Counter c = new Counter();

            Thread thread1 = new Thread(c.AddCount);
            Thread thread2 = new Thread(c.AddCount);

            thread1.Start();
            thread2.Start();


            thread1.Join();
            thread2.Join();


            Console.WriteLine("count: {0}", c.count);

            stopwatch.Stop();
            Console.WriteLine("{0} ms", stopwatch.ElapsedMilliseconds);
        }
    }

lock 코드 블록으로 감싸면 한번에 하나의 스레드만 실행할 수 있는 크리티컬 섹션(Critical Section) 이 된다

lock 키워드의 매개변수는 스레드 동기화를 위해 멤버변수로 생성한다

성능 저하를 막기 위해 크리티컬 섹션은 중요한 곳에만 사용한다

'C# > 수업 내용' 카테고리의 다른 글

[C#] 동적 배열  (0) 2021.09.14
[C#] params, out, ref  (0) 2021.09.13
[C#] Iterator, yield  (0) 2021.09.10
[C#] Json을 사용한 인벤토리 만들기 연습  (0) 2021.09.10
[C#] Newtonsoft.Json 파일 읽기, 역직렬화  (0) 2021.09.08