C ++에서의 간단한 스레딩 예제


391

누군가가 C ++에서 두 개의 (Object Oriented) 스레드를 시작하는 간단한 예를 게시 할 수 있습니까?

C 스타일 스레드 라이브러리를 호출하는 것과 달리 run 메소드를 확장 할 수있는 실제 C ++ 스레드 객체를 찾고 있습니다.

나는 응답 한 사람이 크로스 플랫폼 라이브러리로 응답하여 사용하기를 희망하면서 OS 특정 요청을 생략했습니다. 나는 지금 그것을 명백하게 만들고 있습니다.


답변:


561

다음과 같이 스레드를 실행할 함수를 작성하십시오.

void task1(std::string msg)
{
    std::cout << "task1 says: " << msg;
}

이제 thread위와 같이 궁극적으로 위 함수를 호출 할 객체를 만듭니다 .

std::thread t1(task1, "Hello");

( 수업 #include <thread>에 액세스 해야합니다 std::thread)

생성자의 인수는 스레드가 실행할 함수와 함수의 매개 변수입니다. 구성시 나사산이 자동으로 시작됩니다.

나중에 스레드가 함수 실행을 완료하기를 기다리려면 다음을 호출하십시오.

t1.join(); 

결합은 새 스레드를 호출 한 스레드가 자체 스레드를 계속 실행하기 전에 새 스레드의 실행이 완료 될 때까지 대기 함을 의미합니다.


코드

#include <string>
#include <iostream>
#include <thread>

using namespace std;

// The function we want to execute on the new thread.
void task1(string msg)
{
    cout << "task1 says: " << msg;
}

int main()
{
    // Constructs the new thread and runs it. Does not block execution.
    thread t1(task1, "Hello");

    // Do other things...

    // Makes the main thread wait for the new thread to finish execution, therefore blocks its own execution.
    t1.join();
}

std :: thread에 대한 자세한 내용은 here

  • GCC에서로 컴파일하십시오 -std=c++0x -pthread.
  • 컴파일러가 (C ++ 11) 기능을 지원한다는 점에서 모든 운영 체제에서 작동합니다.

4
@ Preza8 VS10은 C ++ 11의 많은 기능을 지원하지 않습니다. VS12 및 VS13은 스레드를 지원합니다.
jodag

3
"4.7 이하의 GCC 버전에서는 -std=c++0x(대신 -std=c++0x) 사용"이라는 주석 에서 두 번째 "c ++ 0x"는 대신 "c ++ 11"이어야한다고 생각하지만 편집이 너무 작기 때문에 변경할 수 없습니다.
zentrunix

1
@MasterMastic std :: thread t1 (task1, "Hello") 대신 std :: thread t1 (& task1, "Hello") 대신 함수의 참조를 전달하면 어떤 차이가 있습니까? 이 경우 함수를 포인터로 선언해야합니까?
user2452253

3
@ user2452253 "task1"을 전달하면 실행하려는 함수에 대한 포인터를 전달합니다 (좋습니다). 당신이 "& 작업 1"을 통과하면 당신은 함수의 포인터에 대한 포인터를 전달하고, 결과는 아마도 너무 예쁘고 매우 정의되지 않을 것이다 (그것은 임의의 명령을 차례로 실행하려고처럼 될 것입니다. 올바른 확률 당신이 단지 힘 지옥으로가는 관문을여십시오). 실제로 함수 포인터 (함수가 시작되는 주소 값을 가진 포인터)를 전달하고 싶습니다. 그래도 문제가 해결되지 않으면 알려주세요. 행운을 빕니다!
MasterMastic

2
@curiousguy 글쎄, 올바른 방법은 실행하려는 함수의 포인터를 전달하는 것입니다. 이 경우 기능은 task1입니다. 따라서 함수 포인터도로 표시됩니다 task1. 하지만 내가 잘못 생각하기 때문에 이것을 가져 주셔서 감사합니다 그리고 동등의 &task1그것은, 내가 함수의 포인터가 포인터를 추측 그렇다면 당신은 (쓰기로 선택 형성하는 중요하지 않습니다 그래서, &&task1- 나쁜 것 ). 관련 질문 .
MasterMastic

80

글쎄, 기술적으로 그러한 객체는 C 스타일 스레드 라이브러리를 통해 빌드 될 것입니다 .C ++ std::thread은 c ++ 0x 의 스톡 모델 만 지정했기 때문에 방금 중단되었지만 아직 구현되지 않았기 때문입니다. 문제는 다소 체계적이며, 기술적으로 기존 c ++ 메모리 모델은 모든 '이전에 발생하는'사례에 대해 잘 정의 된 의미를 허용 할만큼 엄격하지 않습니다. 한스 보엠 (Hans Boehm)은 얼마 전에 그 주제에 관한 논문을 썼고 그 주제에 대한 c ++ 0x 표준을 망치는 데 도움이되었습니다.

http://www.hpl.hp.com/techreports/2004/HPL-2004-209.html

그것은 실제로 잘 작동하는 여러 플랫폼 간 스레드 C ++ 라이브러리가 있다고 말했습니다. 인텔 스레드 빌딩 블록에는 c ++ 0x 표준과 거의 비슷한 tbb :: thread 객체가 포함되어 있으며 Boost에는 동일한 기능을 수행하는 boost :: thread 라이브러리가 있습니다.

http://www.threadingbuildingblocks.org/

http://www.boost.org/doc/libs/1_37_0/doc/html/thread.html

boost :: thread를 사용하면 다음과 같은 것을 얻을 수 있습니다.

#include <boost/thread.hpp>

void task1() { 
    // do stuff
}

void task2() { 
    // do stuff
}

int main (int argc, char ** argv) {
    using namespace boost; 
    thread thread_1 = thread(task1);
    thread thread_2 = thread(task2);

    // do other stuff
    thread_2.join();
    thread_1.join();
    return 0;
}

8
부스트 스레드는 훌륭합니다. 내 유일한 문제는 마지막 클래스를 사용했을 때 기본 클래스 스레드 핸들에 실제로 액세스 할 수 없다는 것입니다. win32에는 스레드 핸들이 필요한 많은 톤이 있으므로 핸들을 공개하기 위해 조정했습니다.
Orion Edwards

4
boost :: thread의 또 다른 문제는 새 스레드의 스택 크기를 자유롭게 설정할 수 없다는 것입니다.
Edward KMETT

이 코드는이 줄에 대한 boost :: noncopyable 예외를 제공합니다. thread thread_1 = thread (task1); 아마도 이전 버전 (1.32)을 사용하고 있기 때문일 수 있습니다.
Frank

이 범위에서 task1이 선언되지 않았습니까?
Jake Gaston

20

POSIX 운영 체제를위한 POSIX 라이브러리도 있습니다. 호환성 확인

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <iostream>

void *task(void *argument){
      char* msg;
      msg = (char*)argument;
      std::cout<<msg<<std::endl;
}

int main(){
    pthread_t thread1, thread2;
    int i1,i2;
    i1 = pthread_create( &thread1, NULL, task, (void*) "thread 1");
    i2 = pthread_create( &thread2, NULL, task, (void*) "thread 2");

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    return 0;

}

-lpthread로 컴파일

http://en.wikipedia.org/wiki/POSIX_Threads


18
#include <thread>
#include <iostream>
#include <vector>
using namespace std;

void doSomething(int id) {
    cout << id << "\n";
}

/**
 * Spawns n threads
 */
void spawnThreads(int n)
{
    std::vector<thread> threads(n);
    // spawn n threads:
    for (int i = 0; i < n; i++) {
        threads[i] = thread(doSomething, i + 1);
    }

    for (auto& th : threads) {
        th.join();
    }
}

int main()
{
    spawnThreads(10);
}

13

새로운 스레드에서 자체 인스턴스 메소드 중 하나를 호출하는 C ++ 클래스의 예를 검색 할 때이 질문이 나오지만 이러한 답변 중 어떤 것도 사용할 수 없었습니다. 이를 수행하는 예제는 다음과 같습니다.

Class.h

class DataManager
{
public:
    bool hasData;
    void getData();
    bool dataAvailable();
};

Class.cpp

#include "DataManager.h"

void DataManager::getData()
{
    // perform background data munging
    hasData = true;
    // be sure to notify on the main thread
}

bool DataManager::dataAvailable()
{
    if (hasData)
    {
        return true;
    }
    else
    {
        std::thread t(&DataManager::getData, this);
        t.detach(); // as opposed to .join, which runs on the current thread
    }
}

이 예제는 뮤텍스 나 잠금에 들어 가지 않습니다.


2
이것을 게시 해 주셔서 감사합니다. 인스턴스 메소드에서 스레드를 호출하는 일반적인 형식은 다음과 같습니다. Foo f; std :: thread t (& Foo :: Run, & f, args ...); 여기서 Foo는 멤버 함수로 'Run ()'이있는 클래스입니다.
Jay Elston

이것을 게시 해 주셔서 감사합니다. 모든 스레딩 예제가 전역 함수를 사용하는 이유를 진지하게 이해하지 못합니다.
hkBattousai

9

전역 네임 스페이스에서 별도의 함수를 원하지 않는 경우 람다 함수를 사용하여 스레드를 만들 수 있습니다.

람다를 사용하여 스레드를 만들면 얻을 수있는 가장 큰 장점 중 하나는 로컬 매개 변수를 인수 목록으로 전달할 필요가 없다는 것입니다. 캡처 목록을 동일하게 사용할 수 있으며 람다의 클로저 속성이 수명주기를 처리합니다.

다음은 샘플 코드입니다

int main() {
    int localVariable = 100;

    thread th { [=](){
        cout<<"The Value of local variable => "<<localVariable<<endl;
    }}

    th.join();

    return 0;
}

지금까지 C ++ 람다는 특히 간단한 스레드 함수를 위해 스레드를 만드는 가장 좋은 방법이라는 것을 알았습니다.


8

사용하기로 결정한 라이브러리에 따라 다릅니다. 예를 들어 wxWidgets 라이브러리를 사용하는 경우 스레드 작성은 다음과 같습니다.

class RThread : public wxThread {

public:
    RThread()
        : wxThread(wxTHREAD_JOINABLE){
    }
private:
    RThread(const RThread &copy);

public:
    void *Entry(void){
        //Do...

        return 0;
    }

};

wxThread *CreateThread() {
    //Create thread
    wxThread *_hThread = new RThread();

    //Start thread
    _hThread->Create();
    _hThread->Run();

    return _hThread;
}

기본 스레드가 CreateThread 메서드를 호출하면 "Entry"메서드에서 코드 실행을 시작하는 새 스레드가 생성됩니다. 대부분의 경우 스레드를 조인하거나 중지하려면 스레드에 대한 참조를 유지해야합니다. 자세한 정보는 여기 : wxThread documentation


1
스레드를 삭제하는 것을 잊었습니다. 아마도 분리 된 스레드 를 만들려고 했습니까?
AIB

1
그렇습니다. 현재 작업중 인 일부 코드에서 코드를 추출했으며 스레드에 대한 참조가 나중에 어딘가에 결합, 중지 및 삭제하기 위해 어딘가에 저장됩니다. 감사. :)
LorenzCK
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.