Server/Study

[Server] AutoResetEvent

GiveZero 2023. 4. 26. 16:54

AutoResetEvent

using System;
using System.Threading.Channels;

namespace Server
{
    // Event는 커널영역(운영체제)에 요청 -> 큰 비용 부담
    class Lock
    {
        // bool <- 커널
        private AutoResetEvent _available = new AutoResetEvent(true);
        public void Acquire()
        {
            _available.WaitOne(); // 입장 시도
        }

        public void Release()
        {
            _available.Set();
        }
    }
    
    class Program
    {
        private static int _num = 0;
        private static Lock _lock = new Lock();

        static void Thread1()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.Acquire();
                _num++;
                _lock.Release();
            }
        }

        static void Thread2()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.Acquire();
                _num--;
                _lock.Release();
            }
        }
        
        static void Main(string[] args)
        {
            Task t1 = new Task(Thread1);
            Task t2 = new Task(Thread2);
            
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(_num);
        }
    }
}

 

ManualResetEvent

WaitOne, Reset 두개의 행동으로 이루어지기 때문에 Lock 기능을 구현하기에는 적절하지않음

using System;
using System.Threading.Channels;

namespace Server
{
    // Event는 커널영역(운영체제)에 요청 -> 큰 비용 부담
    class Lock
    {
        // bool <- 커널
        private ManualResetEvent _menuAvailable = new ManualResetEvent(false);
        public void Acquire()
        {
            _menuAvailable.WaitOne();
            _menuAvailable.Reset();
        }

        public void Release()
        {
            _available.Set();
        }
    }
    
    class Program
    {
        private static int _num = 0;
        private static Lock _lock = new Lock();

        static void Thread1()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.Acquire();
                _num++;
                _lock.Release();
            }
        }

        static void Thread2()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.Acquire();
                _num--;
                _lock.Release();
            }
        }
        
        static void Main(string[] args)
        {
            Task t1 = new Task(Thread1);
            Task t2 = new Task(Thread2);
            
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(_num);
        }
    }
}

 

Mutex

using System;
using System.Threading.Channels;

namespace Server
{  
    // Mutex : 커널 공유 객체
    // AutoReset, Manul와 다른점
    // bool정보 뿐만 아니라 몇번 Lock을 걸었는지 체크(int)
    // 엉뚱한 곳에서 Release에서 발생하는 것을 탐지
    class Program
    {
        private static int _num = 0;
        private static Mutex _lock = new Mutex();

        static void Thread1()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.WaitOne();
                _num++;
                _lock.ReleaseMutex();
            }
        }

        static void Thread2()
        {
            for (int i = 0; i < 10000; i++)
            {
                _lock.WaitOne();
                _num--;
                _lock.ReleaseMutex();
            }
        }
        
        static void Main(string[] args)
        {
            Task t1 = new Task(Thread1);
            Task t2 = new Task(Thread2);
            
            t1.Start();
            t2.Start();

            Task.WaitAll(t1, t2);

            Console.WriteLine(_num);
        }
    }
}