내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-12-17 15:10

제목

[C#] ConcurrentBag 사용법


병렬처리시 Thread에 안전한 ConcurrentBag을 사용하는 방법에 대해서 이야기해보겠습니다. 우선 그전에 ConcurrentBag이란 무엇인지 알아보겠습니다. ConcurrentBag은 평소 자주 사용하는 List을 병렬처리하여 추가하거나 삭제하는 경우에 데이터가 안전하게 보관되도록 만든 클래스입니다. 사용법은 아주 간단한데요. List와 똑같이 사용하면 됩니다.


List와 같은 방법으로 선언하여 데이터를 추가하였습니다. 현재 각 공간에 1,2,3,4 가 들어있습니다. 여기서 삭제하는 것을 알아보면 List 에서는 Remove, RemoveAt, RemoveAll과 같은 함수가 있습니다. 이때 List에서는 데이터 삭제가 일어나면 각 item들의 인덱스와 링크 주소가 바뀌게 됩니다. 그렇기 때문에 한개의 item을 삭제하고 있는 중에 다른 item을 삭제하면 문제가 생기게 됩니다. 평소 병렬 프로그래밍을 하지 않았다면 전혀 문제가 되지 않았을 것입니다. 왜냐하면 한개를 삭제하고 삭제가 끝나면 다음 item을 삭제하기 때문이죠.

하지만 병렬처리를 하게 되면 한개의 item이 삭제되고 있는 중에 다른 item이 삭제될 수 있어요. 그렇기 때문에 에러가 생기게 됩니다. 이때 에러를 막기 위해서 사용하는 것이 ConcurrentBag인 것입니다. 여기에는 List에 없는 함수가 있는데요. TryPeek과 TryTake입니다. 함수명에 Try가 있기 때문에 반환값은 bool 값인데요. 해당 함수가 성공하면 true 실패하면 false를 반환하는 것을 알 수 있습니다. TryPeek 함수는 해당 ConcurrentBag에서 가장 마지막에 추가된 item이 무엇인지 out 키워드를 통해서 반환하는 함수입니다. 반환할때 해당 ConcurrentBag에서 item이 삭제되지 않습니다. 반대로 TryTake함수는 마지막에 추가된 item이 반환되면서 해당 ConcurrentBag에서 삭제가 됩니다.


그렇기 때문에 필요한 함수를 잘 선택하여 사용하는 것이 좋습니다.

실제 List를 사용하여 Parallel를 돌리게 되면 다음과 같이 에러 메세지가 생길 수 있습니다. 하지만 ConcurrentBag을 이용하면 같은 코드지만 문제 없이 돌아갑니다.



사실 이 내부를 구현하기 위해서는 다양한 작업이 필요한데요. C# 같은 경우에 이런 번거로운 작업을 대신 해주고 있기 때문에 정말 편하게 사용할 수 있는 언어입니다. 단 내부가 어떻게 돌아가고 어떤 방식인지 알고 사용하는 것과 모르고 사용하는 것은 큰 차이가 있겠죠. 다음에 기회가 되면 내부가 어떤식으로 작동하는지에 대해서 이야기해보겠습니다.

출처1

https://math-development-geometry.tistory.com/38

출처2