비어있는 try문 후에 있는 finally 문

안녕하세요! 요즘 멀티쓰레드 공부한다고 .Net 코드를 보고 있는데
이런 코드가 있어서 어떤 의민지 몰라 여쭤봅니다!!

비어있는 try문을 사용하고 finllay에서 중요한 작업을 합니다!

보고있는 함수 전체를 올리겠습니다!

        /// <summary>
        /// Local helper function to Take or Peek an item from the bag
        /// </summary>
        /// <param name="result">To receive the item retrieved from the bag</param>
        /// <param name="take">True means Take operation, false means Peek operation</param>
        /// <returns>True if succeeded, false otherwise</returns>
        private bool TryTakeOrPeek(out T result, bool take)
        { 
            // Get the local list for that thread, return null if the thread doesn't exit 
            //(this thread never add before) 
            ThreadLocalList list = GetThreadList(false);
            if (list == null || list.Count == 0)
            {
                return Steal(out result, take);
            }
 
            bool lockTaken = false;
            try
            {
                if (take) // Take operation
                {
#pragma warning disable 0420
                    Interlocked.Exchange(ref list.m_currentOp, (int)ListOperation.Take);
#pragma warning restore 0420
                    //Synchronization cases:
                    // if the list count is less than or equal two to avoid conflict with any stealing thread
                    // if m_needSync is set, this means there is a thread that needs to freeze the bag
                    if (list.Count <= 2 || m_needSync)
                    {
                        // reset it back to zero to avoid deadlock with stealing thread
                        list.m_currentOp = (int)ListOperation.None;
                        Monitor.Enter(list, ref lockTaken);
 
                        // Double check the count and steal if it became empty
                        if (list.Count == 0)
                        {
                            // Release the lock before stealing
                            if (lockTaken)
                            {
                                try { } //<--- 여기입니다!! 여기!! 👋
                                finally
                                {
                                    lockTaken = false; // reset lockTaken to avoid calling Monitor.Exit again in the finally block
                                    Monitor.Exit(list);
                                }
                            }
                            return Steal(out result, true);
                        }
                    }
                    list.Remove(out result);
                }
                else
                {
                    if (!list.Peek(out result))
                    {
                        return Steal(out result, false);
                    }
                }
            }
            finally
            {
                list.m_currentOp = (int)ListOperation.None;
                if (lockTaken)
                {
                    Monitor.Exit(list);
                }
            }
            return true;
        }

마이크로소프트 사람들이… 어떤 이유에서 저런 코드를 만들어 놓았을까요?

혹시… 저런 패턴으로 사용하시는 분들 계시면 이 패턴에 대한 의견 받아볼 수 있을까요?!

감사합니다!

3개의 좋아요

finally 문은 어떠한 예외가 발생하더라도 실행됩니다. Monitor.Enter를 통해 list에 대한 lock을 취득한 상태에서 스레드가 중단되어 deadlock이 발생하는 것을 막기 위한 목적으로 생각합니다.

7개의 좋아요

@루나시아 님이 말씀하신 것 처럼 스레드가 중간에 중단되도 반드시 처리가 완료되도록 보장하기 위한 방법입니다.
다음 페이지를 읽어 보시면 될거 같습니다.

9개의 좋아요

연휴 끝나고 전달해 주신 링크의 글을 읽어보았습니다.
finally 블록에 있는 코드는 실행 중에 쓰레드가 종료 되어도
끝까지 모두 실행 된 후에 종료 되게 되어있군요!!!

좋은 글 전달해 주셔서 감사합니다! :+1:

5개의 좋아요

질문을 다시 읽고 좀 더 찾아보았는데요. 빈 try-finally블록은 CER이라는 개념과 함께 코드가 예외나 외부 요인으로부터 중단되지 않고 안전하게 실행되도록 하는 코드 중 하나라고 합니다. finally 절에 있는 코드는 try 절이 실행되기 전에 모든 코드가 빌드되고 어떠한 경우에도 실행을 보장할 수 있다고 합니다. 제가 질문 드렸던 코드는 멀티쓰레드 관련 코드였는데 코드의 빈 try-finally 구문을 보시면 lock을 잡은 후 쓰레드가 중단(abort) 되어도 finally 절에 있는 lock 해제 코드가 반드시 실행되도록 해서 @루나시아 님이 말씀하셨던 것 처럼 deadlock이 걸리지 않도록 처리 한 것입니다. Thread.Abort()의 실행은 CLR에서 관리하며 finally 역시 CLR에서 관리되는데 CLR에 메커니즘에선 finally 블록은 Thread.Abort()로 중단되지 않기 때문입니다.

4개의 좋아요