boost :: thread 및 boost :: mutex를 c ++ 11에 해당하는 것으로 대체하는 것이 현명합니까?


153

동기 부여 : 내가 생각하는 이유는 내 천재 프로젝트 관리자가 부스트가 또 다른 의존성이라고 생각하고 "당신이 그것에 의존"하기 때문에 끔찍하다고 생각하기 때문입니다. 내가하고 싶은 작은 이유는 사람들이 코드 작성을 시작하기 때문에 c ++ 11 기능을 배우고 싶기 때문입니다.

  1. #include<thread> #include<mutex>부스트와 부스트 간에 1 : 1 매핑이 있습니까?
  2. 부스트 항목을 c ++ 11로 바꾸는 것이 좋습니다
    . 내 사용법은 원시적이지만 std가 어떤 부스트를 제공하지 않는 예가 있습니까? 아니면 (신성 모독)?

추신 : 나는 GCC를 사용하므로 헤더가 있습니다.


46
IMO Google 코딩 가이드 라인은 여러 가지면에서 어리 석습니다. 예를 들어 그들은 C ++ 11에서 자동을 허용하지 않습니다 ... :)
NoSenseEtAl

5
인용 지침 : [자동]은 독자에게 도움이 될 수있는 확인 된 중복성 (예 : 유형 이름)을 [제거하기 때문에] 가독성을 떨어 뜨립니다.
Andrew Tomazos

31
for (auto it = v.begin () ... :)
NoSenseEtAl

15
@ AndrewTomazos-Fathomling : 정말요? 개인적으로 필자는 반복자의 실제 유형에 대해 신경 쓰지 않았고 지원되는 작업 만 고려했다고 생각합니다 ... 구문 중복은 거의 좋은 생각 (DRY)이 아니라고 주장합니다.
그리즐리

16
BTW 이제 그 바보 같은 지침을 수정 구글 마침내 허용 자동
NoSenseEtAl

답변:


192

Boost.Thread와 C ++ 11 표준 스레드 라이브러리에는 몇 가지 차이점이 있습니다.

  • 부스트는 스레드 취소를 지원하지만 C ++ 11 스레드는 지원하지 않습니다.
  • C ++ 11은을 지원 std::async하지만 Boost는 지원 하지 않습니다
  • Boost에는 boost::shared_mutex다중 판독기 / 단일 작성기 잠금 기능이 있습니다. 유사한는 std::shared_timed_mutex오직 C ++ 14 (이후 사용할 N3891 동안) std::shared_mutex만 C ++ 17 (이후 사용할 N4508 ).
  • C ++ 11 타임 아웃은 Boost 타임 아웃과 다릅니다 (이제 머지 않아 Boost.Chrono가 승인되었습니다).
  • 일부 이름이 다릅니다 (예 : boost::unique_futurevs std::future)
  • 인수 전달 시맨틱은 --- Boost 용도 와 std::thread다르며 복사 가능한 인수가 필요합니다. 이동 전용 유형 (예 : 인수로 전달)을 허용합니다. 의 사용으로 인해 중첩 바인드 표현식 과 같은 자리 표시 자의 의미 도 다를 수 있습니다.boost::threadboost::bindstd::threadstd::unique_ptrboost::bind_1
  • 명시 적으로 호출하지 않는 경우 join()또는 detach()다음 boost::thread소멸자 및 대입 연산자가 호출 detach()에 할당 / 파괴 스레드 객체. C ++ 11 std::thread객체를 사용 std::terminate()하면 응용 프로그램을 호출 하고 중단합니다.

이동 전용 매개 변수에 대한 요점을 명확히하기 위해 다음은 유효한 C ++ 11이며 int임시 소유권 에서 새 스레드가 시작될 때의 std::unique_ptr매개 변수로 소유권을 이전합니다 f1. 그러나 사용하면 내부적으로 boost::thread사용 되므로 복사 할 수 없으므로 작동하지 않습니다. GCC와 함께 제공되는 C ++ 11 스레드 라이브러리 에는 구현에서도 사용 되는 것과 같은 작동을 방해하는 버그 가 있습니다.boost::bindstd::unique_ptrstd::bind

void f1(std::unique_ptr<int>);
std::thread t1(f1,std::unique_ptr<int>(new int(42)));

Boost를 사용하는 경우 컴파일러에서 지원하는 경우 C ++ 11 스레드로 비교적 고통없이 전환 할 수 있습니다 (예 : Linux의 최신 버전의 GCC에는 -std=c++0x모드 에서 사용 가능한 C ++ 11 스레드 라이브러리가 대부분 완벽하게 구현되어 있음 ).

컴파일러가 C ++ 11 스레드를 지원하지 않으면 Just :: Thread 와 같은 타사 구현을 얻을 수 있지만 여전히 종속성입니다.


1
리더와 라이터에 대해 별도의 잠금 / 잠금 해제 방법이 있습니다 (라이터의 경우 lock/ unlock쓰기 대 독자의 경우 'lock_shared / unlock_shared'). 작성자가 사용하지 않는 한 여러 독자가 차단없이 lock_shared를 호출 할 수 있습니다.
Dave S

2
shared_mutex워드 프로세서에 있습니다 boost.org/doc/libs/1_47_0/doc/html/thread/... . 뮤텍스를 공유 또는 독점으로 잠근 다음 해당 잠금 해제 기능을 사용하십시오. 또한이 작업을 수행 (위해 RAII 유형을 사용할 수 있습니다 shared_lock소요 공유 읽기 잠금 및 lock_guardunique_lock독점 잠금을). 이동 전용 유형에 대한 요점을 명확히하려고 노력했습니다.
Anthony Williams

3
부딪히는 또 하나의 사소한 일 : 부스트에서는 실행중인 스레드의 소멸자가 스레드를 분리하고 ( boost.org/doc/libs/1_47_0/doc/html/thread/… ) C ++에서는 실행중인 스레드 호출의 소멸자가 종료됩니다 () (FDIS 30.3.1.3)
Cubbi

3
C ++ 11에서 try_scoped_lock기능은로 다룹니다 std::unique_lock. 뮤텍스를 취하는 생성자 가있다 . 그리고 뮤텍스 std::try_to_lock를 호출한다 . 참조 stdthread.co.uk/doc/headers/mutex/unique_lock/...try_lock()lock()
앤서니 윌리엄스

4
예. Boost.Thread는 필자가 Vicente Botet의 작업으로 작성한 이후 C ++ 11 표준에 훨씬 더 가까워졌습니다.
Anthony Williams

24

std::thread몇 가지 차이점boost::thread 을 제외 하고 는 크게 모델링되었습니다 .

  • boost의 복사 불가능한 1- 핸들 맵 -to-one-os- 스레드 의미론이 유지됩니다. 그러나이 스레드는 공장 기능에서 스레드를 반환하고 컨테이너에 넣을 수 있도록 움직일 수 있습니다.
  • 이 제안은에 취소를 추가 boost::thread하는데 이는 심각한 합병증입니다. 이 변경은 스레드뿐만 아니라 나머지 C ++ 스레딩 라이브러리에도 큰 영향을 미칩니다. 이 큰 변화는 이점 때문에 정당화 될 수 있다고 믿어집니다.
    • 상위 스레드가 취소 될 때 실수로 하위 스레드가 누출되지 않도록 스레드 소멸자가 분리하기 전에 cancel을 호출해야합니다.
    • 취소하지 않고 분리 할 수 ​​있도록하려면 명시 적 분리 부재가 필요합니다.
  • 쓰레드 핸들과 쓰레드 아이덴티티의 개념은 두 개의 클래스로 분리되어있다 boost::thread. 이것은 스레드 ID의보다 쉬운 조작 및 저장을 지원하기위한 것입니다.
  • 다른 결합 가능한 스레드와 비교할 수없는 스레드 ID를 작성하는 기능이 추가되었습니다 ( boost::thread없는). 이것은 이전 호출과 동일한 스레드에서 실행되고 있는지 알고 싶은 코드에 유용합니다 (재귀 뮤텍스는 구체적인 예입니다).
  • 클라이언트가 원하는 경우 기본 OS를 사용하여 스레드를 조작 할 수 있도록 기본 스레드 핸들을 가져 오는 "백도어"가 있습니다.

: 이것은 몇 가지 포인트가 더 이상 유효하므로, 2007 년없는 boost::threadnative_handle댓글이 지적으로, 지금은 기능을하고, std::thread더 이상 취소가 없습니다.

boost::mutex와 사이에 큰 차이가 없습니다 std::mutex.


2
std::thread취소하지 않습니다. 그것은이다 boost::thread그 않습니다!
Anthony Williams

@Anthony interrupt()부스트 : : 스레드를 의미하지 않습니까? 또한 2007 년 이후 변경된 원래 제안 인 것으로 보입니다.
Alex B

4
예, 부스트의 취소를 "중단"이라고합니다. 예, 이것은 오래된 제안입니다. C ++ 11 표준의 최신 공개 초안 (스레드 라이브러리 포함)은 open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf
Anthony Williams

6

로 마이그레이션하지 않는 한 가지 이유가 있습니다 std::thread.

정적 연결을 사용하는 경우 std::thread다음 gcc 버그 / 기능으로 인해 사용할 수 없게됩니다.

즉, 전화를 걸 std::thread::detach거나 std::thread::join예외 또는 충돌이 발생하면 boost::thread이러한 경우에는 정상적으로 작동합니다.


한 버그는 확인되지 않았고 다른 버그는 유효하지 않은 것으로 나타났습니다 libpthread.a. 당신이 말하는 것을 절대적으로 확신합니까?
einpoklum

1
@einpoklum,를 사용하여 작동시킬 수 있어야합니다 ( Wl,--whole-archive -lpthread -Wl,--no-whole-archive예 : stackoverflow.com/a/23504509/72178) . 그러나 연결하는 것은 매우 간단한 방법이 아니며 libpthread.a나쁜 생각으로 간주됩니다.
ks1322

4
이 버그가 현재 2016 년으로 수정되었다고 가정 할 수 있습니까? 버그는 2012 년에 게시되었으며 gcc 4.9.2부터 공식적으로 C ++ 11을 지원하므로 공식 지원 전에 C ++ 11에 대해 불만을 제기 할 수 없습니다.
Splash

6

기업 사례

중간 규모에서 다양한 운영 체제로 실행해야하는 엔터프라이즈 용 소프트웨어를 작성하고 결과적으로 해당 운영 체제에서 다양한 컴파일러 및 컴파일러 버전 (특히 비교적 오래된 버전)으로 빌드하는 경우, 제 제안은 지금은 C ++ 11입니다. 즉 std::thread,를 사용할 수 없으므로를 사용하는 것이 좋습니다 boost::thread.

기본 / 기술 시작 사례

하나 또는 두 개의 운영 체제를 작성하는 경우 대부분 C ++ 11 (예 : VS2015, GCC 5.3, Xcode 7)을 지원하는 최신 컴파일러로만 빌드하면되고 아직은 그렇지 않습니다. 부스트 라이브러리에 따라 std::thread 좋은 옵션이 될 수 있습니다.

내 경험

나는 개인적으로 부분적으로 강화되고 많이 사용되며 호환성이 높고 일관성이 높은 라이브러리와 같은 부스트 ​​대 매우 현대적인 대안입니다. 스레딩과 같은 복잡한 프로그래밍 주제의 경우 특히 그렇습니다. 또한 boost::thread방대한 환경, 컴파일러, 스레딩 모델 등에서 전반적으로 큰 성공을 거두었고 일반적으로 부스트를 선택했습니다.


1
@UmNyobe 그는 맞습니다. C ++ 11 스레딩의 많은 구현이 너무 깨져서 사람들이 그것을 사용한다고 생각하는 것에 놀랐습니다.
StaceyGirl


1

C ++ 17에 추가 된 std :: shared_mutex와 관련하여

다른 답변은 일반적인 차이점에 대한 개요를 제공합니다. 그러나 std::shared_mutex부스트 해결 에는 몇 가지 문제가 있습니다.

  1. 업그레이드 가능한 뮤트. 이것들은 없습니다 std::thread. 이것은 다른 작가가 당신에게 들어가기 전에 독자를 작가로 업그레이 드할 수있게합니다 . 이를 통해 읽기 모드에서 큰 계산 (예 : 데이터 구조 재 인덱싱)을 사전 처리 한 다음 쓰기 잠금을 잠시 ​​유지하면서 재 인덱스를 적용하도록 업그레이드 할 수 있습니다.

  2. 공평. 를 사용하여 지속적인 읽기 활동을하는 std::shared_mutex경우 작성자는 무기한으로 소프트 락됩니다. 다른 독자가 오면 항상 우선권이 부여되기 때문입니다. 로 boost:shared_mutex, 모든 스레드가됩니다 결국 우선 순위를 부여한다. (1) 독자와 작가 모두 굶어 죽지 않을 것입니다.

이것의 중요한 점은 다운 타임이없고 높은 경합이없는 처리량이 많은 시스템을 사용 std::shared_mutex하는 경우 우선 순위 시스템을 수동으로 구축하지 않으면 작동하지 않습니다. boost::shared_mutex경우에 따라 문제를 해결해야 할 수도 있지만 즉시 사용할 수 있습니다. 나는 그 std::shared_mutex행동이 그것을 사용하는 대부분의 코드에서 일어나기를 기다리는 잠재적 인 버그 라고 주장 한다.

(1) 사용 하는 실제 알고리즘 은 OS 스레드 스케줄러를 기반으로합니다. 내 경험에 따르면, 읽기가 포화 상태이면 OSX / Linux보다 Windows에서 더 긴 일시 중지 (쓰기 잠금을 얻을 때)가 있습니다.


0

나는 boost 대신 std에서 shared_ptr을 사용하려고 시도했지만 실제로이 클래스의 gcc 구현에서 버그를 발견했습니다. 소멸자가 두 번 호출되어 내 응용 프로그램이 중단되었습니다 (이 클래스는 스레드로부터 안전해야하며 이러한 문제가 발생하지 않아야 함). boost :: shared_ptr로 이동 한 후 모든 문제가 사라졌습니다. C ++ 11의 현재 구현은 여전히 ​​성숙하지 않습니다.

부스트에는 더 많은 기능이 있습니다. 예를 들어 std 버전의 헤더는 직렬화기를 스트림에 제공하지 않습니다 (예 : cout << duration). Boost에는 자체 등을 사용하는 많은 라이브러리가 있지만 표준 버전과 협력하지 않습니다.

요약하면-이미 boost를 사용하여 작성된 응용 프로그램이있는 경우 C ++ 11 표준으로 이동하는 대신 코드를 유지하는 것이 안전합니다.


4
shared_ptr소멸자가 thread 세이프 일 필요는 없습니다, 그것의 정의되지 않은 동작은 다른 스레드가 그것을 파괴하는 동안 개체에 액세스하는 하나 개의 스레드를 가지고있다. GCC의 shared_ptr에서 버그를 발견했다고 생각되면 그것을보고하십시오 . 그렇지 않으면 확률의 균형에 따라 잘못 사용하고 있습니다.
Jonathan Wakely 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.