2022년 3월 3일 목요일

[C# Lock]

 using System;

using System.Threading;
using System.Threading.Tasks;

namespace ServerCore
{

    /// <summary>
    /// lock
    /// 준비물: object!(딱히 데이터 저장용으로 사용하는것은 아니다)
    /// </summary>
    ///
    ///
    ///
    ///
    ///
    ///
    /// <summary>
    /// 멀티스레드에서 읽는것은 문제가 되지 않는다
    /// 다른 스레드에서 쓰기 시작할때 문제가 된다!!! 쓰는게 중요!
    ///
    ///
    ///
    ///
    ///
    /// </summary>
    class Program
    {
        static int number = 0;

        static object _obj = new object();


        static void Thread_1()
        {
            for (int i = 0; i < 10000; i++)
            {
                ///상호배제 Mutual Exclusive(서로 배재한다,이기적인사용)
                /// 이 블럭안은 싱글 스레드라고 볼 수 있다.
                /// 대부분의 언어마다 이런것이 있음
                /// C++ -> std::mutex
                /// CriticalSection 등등
                ///
                ///문제는
                ///관리하기가
                ///힘들다
                /*try
                {
                    Monitor.Enter(_obj);
                    number++;
                    return; ///리턴이 있어도 finally는 무조건 탄다!

                }
                finally
                {
                    Monitor.Exit(_obj);
                }*/


                ///내부는 Monitor.Enter와 같음
                lock (_obj)
                {
                    number++;
                    ///자물쇠가 안되있으면 잠구고 빠져나올대 알아서 풀겟다
                }


                /*Monitor.Enter(_obj);///비유 =>기내 1인용 화장실 문잠그기
                {
                    number++;
                    ///실수로 안에서 리턴해버린다?
                    ///return; ///프로그램이 멈춘다  데드락 상황이 된다..(락이 죽엇다)
                }
                Monitor.Exit(_obj);///비유 =>기내 1인용 화장실 문열기*/
            }
        }



        static void Thread_2()
        {
            for (int i = 0; i < 10000; i++)
            {
                Monitor.Enter(_obj);

                lock (_obj)
                {
                    number--;
                    ///자물쇠가 안되있으면 잠구고 빠져나올대 알아서 풀겟다
                }

               

                Monitor.Exit(_obj);
            }
        }





        static void Main(string[] args)
        {
            //number++; /// ++ 이라는 단계가 눈으로 보기에는 한단계 이지만 어셈블리어로 보면 3단계에 걸쳐 일어난다.


            /// 이런식으로 진행된다
            /// int temp = number;
            /// temp += 1;
            /// number = temp;
            /// 이런식으로 진행된다

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



            Task.WaitAll(t1, t2);

            ///분명 결과는 0이 나와야 하는데 이상한 값이나온다...
            ///경합 조건때문이다!(RACE CONDITION)

            Console.WriteLine(number);
        }
    }
}

댓글 없음:

댓글 쓰기

git rejected error(feat. cherry-pick)

 문제 아무 생각 없이 pull을 받지않고 로컬에서 작업! 커밋, 푸시 진행을 해버렷다. push에선 remote와 다르니 당연히 pull을 진행해라고 하지만 로컬에서 작업한 내용을 백업하지 않고 진행하기에는 부담스럽다(로컬작업 유실 가능성) 해결하려...