web-dev-qa-db-ja.com

C++でのスレッドの簡単な例

誰かがC++で2つの(オブジェクト指向)スレッドを開始する簡単な例を投稿できますか。

私は、Cスタイルのスレッドライブラリを呼び出すのではなく、runメソッド(またはそれに似たもの)で拡張できる実際のC++スレッドオブジェクトを探しています。

更新 - 私が答えた人は誰でも使うためにクロスプラットフォームのライブラリで答えることを期待して、私はどんなOS特有の要求も省きました。私は今それを明確にしています。

378
Zak

スレッドに実行させたい関数を作成します。例えば:

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に関する詳細はこちら

  • GCCでは、-std=c++0x -pthreadを付けてコンパイルします。
  • コンパイラがこの(C++ 11)機能をサポートしていれば、どのオペレーティングシステムでも動作するはずです。
500
MasterMastic

C++はc ++ 0xでstock std::thread モデルを指定しただけなので、技術的にはそのようなオブジェクトはCスタイルのスレッドライブラリ上に構築されることになります。問題はやや体系的で、技術的には既存の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;
}
78
Edward KMETT

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

19
#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);
}
11
Caner

新しいスレッドで独自のインスタンスメソッドの1つを呼び出す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
    }
}

この例はミューテックスやロックには入りません。

8
livingtech

それはあなたが使うことに決めたライブラリに大きく依存します。たとえば、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ドキュメント

7
LorenzCK

グローバル名前空間に別の関数が必要でない限り、スレッドを作成するためにラムダ関数を使うことができます。

ラムダを使用してスレッドを作成することの大きな利点の1つは、引数リストとしてローカルパラメータを渡す必要がないということです。キャプチャリストを同じように使用することができ、lambdaのクロージャプロパティがライフサイクルの面倒を見ます。

これがサンプルコードです

int main() {
    int localVariable = 100;

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

    th.join();

    return 0;
}

これまでのところ、C++のラムダは、特に単純なスレッド関数の場合にスレッドを作成する最良の方法であることがわかりました。

5
Daksh

// multithread.cpp:スレッドとクリティカルセクションを使用するC++のスレッドの簡単な例。

#include "stdafx.h"
#include <thread>
#include <iostream>
#include<fstream>
#include <windows.h>

using namespace std;


bool flag = 1;
auto path = "D:\\temp";
void writestatus(int i, int j);
CRITICAL_SECTION cs;

void workerThread(int j)
{
    int i = 1;
    ofstream f2;
    char buff[150] = { 0 };
    while (flag)
    {
        sprintf_s(buff, 150, "D:\\temp\\MyTemp_%d%03d.txt", j, i++);

        //str.append("%d", i++);
        f2.open(buff);
        f2 << buff;
        f2.close();
        //Sleep(10);
    }
    EnterCriticalSection(&cs);
    writestatus(i, j);
    LeaveCriticalSection(&cs);
}

void writestatus(int i, int j)
{
    ofstream f1;
    char buff[150] = { 0 };
    f1.open("D:\\temp\\status.txt", ios_base::app);
    sprintf_s(buff, 150, "%d Writes %d files \n", j, i++);
    if (f1)
    {
        f1 << buff;
    }
    else
    {
        MessageBeep(1);
    }
    f1.close();
}

int main()
{
    system("del d:\\temp\\*.txt");

    InitializeCriticalSection(&cs);
    thread t1(workerThread, 1);
    thread t2(workerThread, 2);
    thread t3(workerThread, 3);
    thread t4(workerThread, 4);
    thread t5(workerThread, 5);

    Sleep(250);
    flag = 0;
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    t5.join();
    return 0;
}
0
Anirudha Ketkar