유니티

c# lock 키워드

공대녀J 2022. 10. 4. 15:41
public class PacketQueue
{
    struct PacketInfo
    {
        public int offset;
        public int size;
    };
    
    //데이터가 삽입될 버퍼
    private MemoryStream m_streamBuffer;
    //패킷 정보 관리 리스트
    private List<PacketInfo> m_offsetList;
    //총 데이터의 오프셋
    private int m_offset = 0; 
    
    //lock 파라미터에 사용될 임의의 객체 생성. 설명에 추가.
    private Object lockObj = new Object();
    
    public PacketQueue()
    {
        m_streamBuffer = new MemoryStream();
        m_offsetList = new List<PacketInfo>();
    }
    
    public int Enqueue(byte[] data, int size)
    {
        PacketInfo info = new PacketInfo();
        
        info.offset = m_offset;
        info.size = size;
        
        lock(lockObj)
        {
            // m_offsetList도 lock 구문에 함께 삽입하여 패킷 데이터 버퍼의 정보와 동기화
            m_offsetList.Add(info);
            
            m_streamBuffer.Position = m_offset;
            
            // data, position으로부터의 offset, 데이터 크기를 매개변수로 갖는다.
            m_streamBuffer.Write(data, 0, size);
            m_streamBuffer.Flush();
            m_Offset+=size;
        }
        
        //삽입된 데이터의 사이즈 반환.
        return size;
    }

lock으로 설정된 블록을 한번에 하나의 스레드에서만 실행할 수 있도록 해준다. 

-> 다른 스레드는 lock이 해제될 때까지 대기한다.

lock이 유지되는 동안 lock을 보유하는 스레드는 lock을 다시 획득하고 해제할 수 있다.

 

lock 파라미터에는 임의의 객체를 사용할 수 있으며, 주로 object 타입의 private 필드를 지정한다고 한다.

lock 파라미터에 넣어주는 임의의 객체는 lock을 하기 위한 열쇠로 생각하면 좋다.

 

따라서, lock 파라미터에 들어갈 객체는 

1. 전용 개체 인스턴스 (예 : private readonly Object lockObj = new Object(); )

2. 코드의 관련 없는 파트에서 잠금 개체로 사용되지 않을 가능성이 있는 다른 인스턴스

 

교착 상태와 잠금 경합 에러가 발생할 수 있기 때문에, 

 

1. this

2. Type 형 인스턴스

3. 문자열 인스턴스 

 

는 lock 파라미터로 넣지 않도록 한다.