엄범


그냥 락 거는 것 보다, 다음 API들을 사용하는게 좋다.


스코프를 벗어나면 자동으로 해제되는 lock을 걸기 위해서는 (since C++ 17 || boost)

```cpp

#include <mutex>

std::mutex mutex1;

std::mutex mutex2;

std::scoped_lock lock(mutex1, mutex2);

// lock.unlock();

```

이는 ``cpp std::lock_guard``에 여러 mutex들을 한번에 lock할 수 있는 기능을 추가한 완전한 상위 호환 API다. 

mutex 하나 넘길 때도 퍼포먼스 걱정 안해도 된다고 함.


다양한 기능을 지원하는 unique_lock

근데 약간의 성능 패널티가 있다고 함.


충돌이 거의 없는 경우 lock을 거는 오버헤드가 적은 spinlock(atomic_flag)을 쓰자.

lock을 acquire하고 release하는건 syscall을 부르는 꽤 비싼 연산이다.

spinlock은 변수 하나의 0, 1을 체크해서 자원이 점유되고 있는지를 체크하는 lock이다.

자원이 점유 중이면, 릴리즈될 때 까지 while돌면서 계속 체크한다.

따라서 충돌이 발생하지 않는 경우 CPU를 많이 소모할 수 있지만, 충돌이 드물게 발생하는 경우라면 spinlock을 사용하는게 속도에 도움이 될 수 있다.


`` std::atomic_flag``로 간단히 구현할 수 있다.

https://en.cppreference.com/w/cpp/atomic/atomic_flag


* std::atomic_flag와 std::atomic<bool>의 차이?

``cpp atomic_flag.test_and_set()``은 변수 test-and-set을 한 과정의 atomic operation으로 처리하기 때문에 spinlock을 구현하려면 atomic_flag를 사용하는게 좋다.
``cpp atomic<bool>``은 if 체크면 체크만, 할당이면 할당만 원자적 연산을 보장해준다. 체크하면서 동시에 할당하는 것도 메서드로 지원하는 것 같기는 한데, 뭔가 spinlock으로 쓰라고 있는 건 아닌 듯.

그렇다고 ``cpp atomic<bool>``이 쓸모 없는거냐 하면 그 것도 아닌게, 스레드 내부의 running을 나타내는 변수 등에 쓰기에 적합하다.