본문 바로가기

C#

[C#] Multi-threading Programming - Memory Barrier, DeadLock

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ServerCore
{
    class GameManager
    {
        static object _lock = new object();

        public static void Test()
        {
            lock(_lock)
            {
                UserManager.UserManager_TestForDeadLock();
            }
        }

        public static void GameManager_TestForDeadLock()
        {
            lock(_lock)
            {

            }
        }
    }

    class UserManager
    {
        static object _lock = new object();

        public static void Test()
        {
            lock (_lock)
            {
                GameManager.GameManager_TestForDeadLock();
            }
        }

        public static void UserManager_TestForDeadLock()
        {
            lock (_lock)
            {

            }
        }
    }


    class Program
    {
        static int num = 0;
        static object _obj = new object(); //자물쇠 개념.
        
        volatile static bool _stop = false;
        //volatile = 코드에서 최적화 금지 + 캐시 무시하고 최신 값을 가져가라
        public static void Thread_1()
        {
            Console.WriteLine("thread 1 start");

            for (int i = 0; i < 10000; i++)
            {
                GameManager.Test();
            }

            // Interlocked 실습
            int num = 0;
            int original = Interlocked.CompareExchange(ref num, 1, 0);
            //Interlocked.CompareExchange(a, b, c): a가 c일 경우 b로 한번에 바꾸어준다.
            if (original == 0) Console.WriteLine("wow!!");
            
            while (_stop == false)
            {
                lock(_obj)
                {
                    //누군가 stop 신호를 해주기를 기다린다
                    Interlocked.Increment(ref num); //경합조건
                }
            }

            Console.WriteLine("thread 1 ended");
        }

        public static void Thread_2()
        {
            Console.WriteLine("thread 2 start");

            for (int i=0; i<10000; i++)
            {
                UserManager.Test();
            }


            while (_stop == false)
            {
                Monitor.Enter(_obj);
                //누군가 stop 신호를 해주기를 기다린다
                Interlocked.Decrement(ref num); //경합조건
                Monitor.Exit(_obj);
            }

            Console.WriteLine("thread 2 ended");
        }

        public static void Main(string[] args)
        {

            Task t1 = new Task(Thread_1);
            Task t2 = new Task(Thread_2);
            
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine($"thread work ended");

            
            Thread.Sleep(1000); //1초
            _stop = true;
            
            Console.WriteLine("call stop");
            
            Console.WriteLine("wait for end");
            
            t1.Wait();
            t2.Wait();
            
            Thread.MemoryBarrier(); //가시성 확보
            
            Console.WriteLine($"end completed, thread num = {num}");


        }
    }
}





//for (int i = 0; i < 5; i++)
//{
//    Task t = new Task(() => { while (true) { } }, TaskCreationOptions.LongRunning);
//    t.Start();
//}
//ThreadPool.SetMinThreads(1, 1);
//ThreadPool.SetMaxThreads(5, 5);
//for (int i = 0; i < 4; i++)
//{
//    ThreadPool.QueueUserWorkItem((obj) => { while (true) { }});
//}
//ThreadPool.QueueUserWorkItem(MainThread); //직원 준비되어 있는 상태


//Thread t = new Thread(MainThread);
//정직원
//c++과 달리 foreground 디폴트.
//t.IsBackground = true;
//t.Name = "Test Thread";
//t.Start();
//Console.WriteLine("Helloo");
//while (true) { }

//static void MainThread(object state)
//{
//    for (int i = 0; i < 4; i++)
//    {
//        Console.WriteLine("main thread is running ...");
//    }
//}

 

[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버