[Rust] 스레드 간의 데이터 공유

스레드를 사용하다보면 둘 이상의 스레드에서 사용할 공용 변수를 두고 써야할 상황이 많다.
그리고 이러한 상황은 데이터 레이스 등의 심각한 버그를 야기하는 원인 중 하나이기도 하다.

러스트에서는 이런 문제를 어떻게 해결할까?

일단 다른 언어들처럼 변수를 밖에 두고, 클로저의 캡쳐를 통해 접근을 시도해보자. image

image ?? 값이 바뀌지 않았다.
클로저는 변수의 값을 복사하기만 하지, 참조하진 않기 때문이다. 클로저가 기억하는건 진짜 num이 아니라 num의 값 1이다...

그래서 제대로 접근해서 값을 변경시키려면 공유변수의 주소값을 공유하는 형태가 되어야한다.
아래 코드는 unsafe를 발라놓은 아주 나쁜 코드지만, 일단 돌아가긴 한다.
라이프타임 문제때문에 data를 정적변수로 놓아놨다. 그리고 정적변수의 수정은 unsafe 블록에서만 할 수 있다.. image

image 여튼 이렇게 짜면 안된다.

가장 정석적으로 데이터 공유를 하는 방법은, 스마트포인터 Arc와 Mutex를 사용하는 것이다.
Mutex로 값을 생성하고, 그걸 다시 Arc로 감싼다.
Arc와 Mutex의 관계는 Rc와 Refcell의 관계와 거의 같다고 한다. 이건 따로 다루도록 하겠다...

그리고 사용시에는 Arc의 복제본을 생성해서 캡쳐하고, 클로저에서는 lock으로 상호배제를 걸면서 포인터값을 획득한다. image

image 대충 이런식으로 쓰면 된다. Mutex로 동기화까지 처리되니 충돌도 없고 잘 돌아간다. image 데드락만 조심하면 된다.
참고로, Mutex는 그 자체로 스마트포인터이기도 하다. image


참조
https://rinthel.github.io/rust-lang-book-ko/ch16-03-shared-state.html