- Auto Reset Event : 문(Signal)이 자동으로 잠긴다
 - Manual Reset Event : 문(Signal)이 수동으로 잠긴다
 
class Lock
{
    AutoResetEvent _available = new AutoResetEvent(true/* 처음은 입장가능 */);   
    public void Acquire()
    {
        _available.WaitOne();   // 입장시도
        // Auto : 입장이 되면 자동으로 다음 입장은 막는다
    }
    public void Release()
    {
        _available.Set();
    }
}
이번엔 Manual로 구현해보자
class Lock
{
    ManualResetEvent _available = new ManualResetEvent(true/* 처음은 입장가능 */);   
    public void Acquire()
    {
        _available.WaitOne();   // 입장시도
        _available.Reset();     // 문을 닫는다
        // 단, Wait와 Reset을 두 단계로 나누니 쓰레드 세이프 하지못함
        // 그럼 이걸 왜 쓰나?
        // 입장시도와 문을 닫는 행위를 별도로 해야할때 사용하면 된다.
    }
    public void Release()
    {
        _available.Set();
    }
}
추가로 Mutex를 써보자
class Program
{
    static int _num = 0;
    static Mutex _lock = new Mutex();
    static void Thread_1()
    {
        for(int i = 0; i < 100000; i++)
        {
            _lock.WaitOne();
            _num++;
            _lock.ReleaseMutex();
        }
    }
    static void Thread_2()
    {
        for(int i = 0; i < 100000; i++)
        {
            _lock.WaitOne();
            _num--;
            _lock.ReleaseMutex();
        }
    }
    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);
    }
}
해보면 SpinLock보다 훨씬느리다
 EventLock처럼 커널단까지 가야해서인데
 그럼 다시 EventLock과 Mutex는 무슨차이인가?
Mutex는 내부적으로 많은 정보를 갖고있다.
- 몇 번 락을 잡았는지
 - Mutex를 락잡은 쓰레드 정보
 
이런 정보를 갖고있기에 일반 SpinLock보다는 훨씬느리게 된다