C++11におけるヘッダファイルthreadの使用
17312 ワード
C++11には、主にstd::threadスレッドクラスを宣言するヘッダファイルが追加されています.C++11の標準クラスstd::threadはスレッドをカプセル化した.std::threadはスレッドオブジェクトを表します.C++11のstd::threadを適用すると、マルチスレッドプログラムのシフトが容易になります.
C++標準ライブラリのヘッダファイルで、C++11標準のスレッドを表すクラス、反発アクセスのためのクラス、メソッドなどが定義されています.
クラスstd::threadはスレッドを表します.初期化時にスレッドの実行関数(または呼び出すことができるオブジェクト)が与えられます.スレッドオブジェクトが構築されると、実行が開始されます.デフォルトでは、C++11のサブスレッドは、メインスレッドに合流する必要があります.すなわち、メインスレッドでthread::join()関数を呼び出す必要があります.これにより、サブスレッドがまだ実行されており、メインスレッドが実行終了して取り消されることを回避します.
サブスレッドの実行関数にパラメータが必要な場合は、std::threadオブジェクト構築関数のパラメータリストに実パラメータリストを書くことができます.呼び出し可能オブジェクト(callable object)をパラメータとしてサブスレッドの構造関数に渡すと、その呼び出し可能オブジェクトはサブスレッドにコピーされます.呼び出し可能なオブジェクトの左の値をサブスレッドに参照する必要がある場合は、std::ref()を使用してオブジェクトの参照を生成し、参照値をサブスレッドに転送します.
C++11で定義されたスレッドはオペレーティングシステムのスレッドに対応しています.つまり、私たちが生成したスレッドはオペレーティングシステムのスケジューリングを直接受け入れています.1つのプロセスで作成できるスレッドの数や、1つのオペレーティングシステムで作成できる総スレッドデータなどは、実行時のオペレーティングシステムによって制限されています.
std::threadでは主に3種類の関数を宣言する:(1)、構造関数、コピー構造関数(コピー構造関数が無効になっていることは、threadがコピー構造されてはいけないことを意味するが、転送(move)または交換(swap))および構造関数;(2)、メンバー関数;(3)、静的メンバー関数(hardware_concurrency、ハードウェアの同時特性を検出し、Returns the number of hardware thread contexts).
std::threadクラスメンバー関数:
(1)、get_id:スレッドIDを取得し、std::thread::idのタイプのオブジェクトを返します.
(2)、joinable:スレッドがjoinされるかどうかを確認します.threadオブジェクトがアクティブな実行可能スレッドを識別しているかどうかを確認します.デフォルトで構築されたthreadオブジェクト、joinが完了したthreadオブジェクト、detachが完了したthreadオブジェクトはjoinableではありません.
(3)、join:この関数を呼び出すと、現在のスレッドがブロックされます.joinのstd::threadオブジェクトによって識別されるスレッドの実行が終了するまで、呼び出し者(caller)が存在するスレッドをブロックする.
(4)、detach:現在のスレッドオブジェクトが表す実行例をスレッドオブジェクトから分離し、スレッドの実行を単独で行うことができる.スレッドの実行が完了すると、割り当てられたリソースが解放されます.
(5)、native_handle:この関数はstd::threadの具体的な実装に関連するスレッドハンドルを返します.native_handle_typeはthreadクラスとオペレーティングシステムSDK APIを接続する橋渡しであり、Linux g+(libstdc+)ではnative_handle_typeは実はpthreadの中のpthreadですtタイプは、threadクラスの機能が私たちの要求を満たすことができない場合(例えば、スレッドの優先度を変更する場合)、threadクラスインスタンスのnative_handle()は、パラメータとして関連するpthread関数をディレクトリに呼び出すために値を返します.This member function is only present in class thread if the library implementation supports it. If present, it returns a value used to access implementation-specific information associated to the thread.
(6)、swap:2つのスレッドオブジェクトが表す最下位ハンドルを交換します.
(7)、operator=:moves the thread object
(8)、hardware_concurrency:静的メンバー関数で、現在のコンピュータで最大のハードウェア同時スレッド数を返します.基本的にプロセッサのコア数と見なすことができます.
またstd::thread::idはスレッドIDを表し、実行時オペレーティングシステム内でそのスレッドを一意に識別できる識別子を定義するとともに、その値は識別されたスレッドの状態を示すこともできる.Values of this type are returned by thread::get_id and this_thread::get_id to identify threads.
スレッド実行コードで現在の呼び出し元スレッドを操作する必要がある場合があります.この場合、C++11には名前空間が定義されています.this_thread、このネーミングスペースもget_を含むヘッダファイルに宣言されます.id()関数は、現在の呼び出し者スレッドのIDを取得するために使用される.yield()関数は、呼び出しスレッドを実行状態から飛び出し、現在のスレッドが実行を放棄し、オペレーティングシステムが別のスレッドをスケジューリングして実行を継続するオペレーティングシステムに再渡すために使用できます.sleep_until()関数は、スレッドを指定された時刻(time point)にスリープし、スレッドが再起動される.sleep_for()関数は、指定されたタイムスライス(time span)をスレッドをスリープし、そのスレッドが再起動されるが、スレッドスケジューリングなどの理由で、実際のスリープはsleep_よりも実際にスリープされる可能性がある.durationが表すタイムスライスはもっと長い.
std::thread:Class to represent individual threads of execution. A thread of execution is a sequence of instructions that can be executed concurrently with other such sequences in multithreading environments, while sharing a same address space.
std::this_thread:This namespace groups a set of functions that access the current thread.
次は、他の記事のcopyのテストコードです.詳細は、対応するreferenceを参照してください.
GitHub:https://github.com/fengbingchun/Messy_Test
C++標準ライブラリのヘッダファイルで、C++11標準のスレッドを表すクラス、反発アクセスのためのクラス、メソッドなどが定義されています.
クラスstd::threadはスレッドを表します.初期化時にスレッドの実行関数(または呼び出すことができるオブジェクト)が与えられます.スレッドオブジェクトが構築されると、実行が開始されます.デフォルトでは、C++11のサブスレッドは、メインスレッドに合流する必要があります.すなわち、メインスレッドでthread::join()関数を呼び出す必要があります.これにより、サブスレッドがまだ実行されており、メインスレッドが実行終了して取り消されることを回避します.
サブスレッドの実行関数にパラメータが必要な場合は、std::threadオブジェクト構築関数のパラメータリストに実パラメータリストを書くことができます.呼び出し可能オブジェクト(callable object)をパラメータとしてサブスレッドの構造関数に渡すと、その呼び出し可能オブジェクトはサブスレッドにコピーされます.呼び出し可能なオブジェクトの左の値をサブスレッドに参照する必要がある場合は、std::ref()を使用してオブジェクトの参照を生成し、参照値をサブスレッドに転送します.
C++11で定義されたスレッドはオペレーティングシステムのスレッドに対応しています.つまり、私たちが生成したスレッドはオペレーティングシステムのスケジューリングを直接受け入れています.1つのプロセスで作成できるスレッドの数や、1つのオペレーティングシステムで作成できる総スレッドデータなどは、実行時のオペレーティングシステムによって制限されています.
std::threadでは主に3種類の関数を宣言する:(1)、構造関数、コピー構造関数(コピー構造関数が無効になっていることは、threadがコピー構造されてはいけないことを意味するが、転送(move)または交換(swap))および構造関数;(2)、メンバー関数;(3)、静的メンバー関数(hardware_concurrency、ハードウェアの同時特性を検出し、Returns the number of hardware thread contexts).
std::threadクラスメンバー関数:
(1)、get_id:スレッドIDを取得し、std::thread::idのタイプのオブジェクトを返します.
(2)、joinable:スレッドがjoinされるかどうかを確認します.threadオブジェクトがアクティブな実行可能スレッドを識別しているかどうかを確認します.デフォルトで構築されたthreadオブジェクト、joinが完了したthreadオブジェクト、detachが完了したthreadオブジェクトはjoinableではありません.
(3)、join:この関数を呼び出すと、現在のスレッドがブロックされます.joinのstd::threadオブジェクトによって識別されるスレッドの実行が終了するまで、呼び出し者(caller)が存在するスレッドをブロックする.
(4)、detach:現在のスレッドオブジェクトが表す実行例をスレッドオブジェクトから分離し、スレッドの実行を単独で行うことができる.スレッドの実行が完了すると、割り当てられたリソースが解放されます.
(5)、native_handle:この関数はstd::threadの具体的な実装に関連するスレッドハンドルを返します.native_handle_typeはthreadクラスとオペレーティングシステムSDK APIを接続する橋渡しであり、Linux g+(libstdc+)ではnative_handle_typeは実はpthreadの中のpthreadですtタイプは、threadクラスの機能が私たちの要求を満たすことができない場合(例えば、スレッドの優先度を変更する場合)、threadクラスインスタンスのnative_handle()は、パラメータとして関連するpthread関数をディレクトリに呼び出すために値を返します.This member function is only present in class thread if the library implementation supports it. If present, it returns a value used to access implementation-specific information associated to the thread.
(6)、swap:2つのスレッドオブジェクトが表す最下位ハンドルを交換します.
(7)、operator=:moves the thread object
(8)、hardware_concurrency:静的メンバー関数で、現在のコンピュータで最大のハードウェア同時スレッド数を返します.基本的にプロセッサのコア数と見なすことができます.
またstd::thread::idはスレッドIDを表し、実行時オペレーティングシステム内でそのスレッドを一意に識別できる識別子を定義するとともに、その値は識別されたスレッドの状態を示すこともできる.Values of this type are returned by thread::get_id and this_thread::get_id to identify threads.
スレッド実行コードで現在の呼び出し元スレッドを操作する必要がある場合があります.この場合、C++11には名前空間が定義されています.this_thread、このネーミングスペースもget_を含むヘッダファイルに宣言されます.id()関数は、現在の呼び出し者スレッドのIDを取得するために使用される.yield()関数は、呼び出しスレッドを実行状態から飛び出し、現在のスレッドが実行を放棄し、オペレーティングシステムが別のスレッドをスケジューリングして実行を継続するオペレーティングシステムに再渡すために使用できます.sleep_until()関数は、スレッドを指定された時刻(time point)にスリープし、スレッドが再起動される.sleep_for()関数は、指定されたタイムスライス(time span)をスレッドをスリープし、そのスレッドが再起動されるが、スレッドスケジューリングなどの理由で、実際のスリープはsleep_よりも実際にスリープされる可能性がある.durationが表すタイムスライスはもっと長い.
std::thread:Class to represent individual threads of execution. A thread of execution is a sequence of instructions that can be executed concurrently with other such sequences in multithreading environments, while sharing a same address space.
std::this_thread:This namespace groups a set of functions that access the current thread.
次は、他の記事のcopyのテストコードです.詳細は、対応するreferenceを参照してください.
#include "thread2.hpp"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace thread_ {
std::atomic global_counter(0);
#ifdef _MSC_VER
///////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/thread/
static void increase_global(int n) { for (int i = 0; i& variable, int n) { for (int i = 0; i {
C() : std::atomic(0) {}
void increase_member(int n) { for (int i = 0; i threads;
std::cout << "increase global counter with 10 threads...
";
for (int i = 1; i <= 10; ++i)
threads.push_back(std::thread(increase_global, 1000));
std::cout << "increase counter (foo) with 10 threads using reference...
";
std::atomic foo(0);
for (int i = 1; i <= 10; ++i)
threads.push_back(std::thread(increase_reference, std::ref(foo), 1000));
std::cout << "increase counter (bar) with 10 threads using member...
";
C bar;
for (int i = 1; i <= 10; ++i)
threads.push_back(std::thread(&C::increase_member, std::ref(bar), 1000));
std::cout << "synchronizing all threads...
";
for (auto& th : threads) th.join();
std::cout << "global_counter: " << global_counter << '
';
std::cout << "foo: " << foo << '
';
std::cout << "bar: " << bar << '
';
return 0;
}
////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/detach/
static void pause_thread(int n)
{
std::this_thread::sleep_for(std::chrono::seconds(n));
std::cout << "pause of " << n << " seconds ended
";
}
int test_thread_detach()
{
// thread::detach: Detaches the thread represented by the object from the calling thread,
// allowing them to execute independently from each other.
std::cout << "Spawning and detaching 3 threads...
";
std::thread(pause_thread, 1).detach();
std::thread(pause_thread, 2).detach();
std::thread(pause_thread, 3).detach();
std::cout << "Done spawning threads.
";
std::cout << "(the main thread will now pause for 5 seconds)
";
// give the detached threads time to finish (but not guaranteed!):
pause_thread(5);
return 0;
}
//////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/get_id/
std::thread::id main_thread_id = std::this_thread::get_id();
static void is_main_thread()
{
// this_thread::get_id: Returns the thread id of the calling thread.
// This value uniquely identifies the thread.
if (main_thread_id == std::this_thread::get_id())
std::cout << "This is the main thread.
";
else
std::cout << "This is not the main thread.
";
}
int test_thread_get_id()
{
// thread::get_id: Returns the thread id
// If the thread object is joinable, the function returns a value that uniquely identifies the thread.
// If the thread object is not joinable, the function returns a default - constructed object of member type thread::id.
is_main_thread();
std::thread th(is_main_thread);
th.join();
return 0;
}
/////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/join/
int test_thread_join()
{
// thread::join: The function returns when the thread execution has completed.
std::cout << "Spawning 3 threads...
";
std::thread t1(pause_thread, 1);
std::thread t2(pause_thread, 2);
std::thread t3(pause_thread, 3);
std::cout << "Done spawning threads. Now waiting for them to join:
";
t1.join();
t2.join();
t3.join();
std::cout << "All threads joined!
";
return 0;
}
///////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/joinable/
static void mythread()
{
// do stuff...
}
int test_thread_joinable()
{
// thread::joinable: Returns whether the thread object is joinable.
// A thread object is joinable if it represents a thread of execution.
std::thread foo; // ,
std::thread bar(mythread);
std::cout << "Joinable after construction:
" << std::boolalpha;
std::cout << "foo: " << foo.joinable() << '
';
std::cout << "bar: " << bar.joinable() << '
';
if (foo.joinable()) foo.join();
if (bar.joinable()) bar.join();
std::cout << "Joinable after joining:
" << std::boolalpha;
std::cout << "foo: " << foo.joinable() << '
';
std::cout << "bar: " << bar.joinable() << '
';
return 0;
}
//////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/thread/operator=/
int test_thread_operator()
{
// thread::operator=: Move-assign thread
// If the object is currently not joinable, it acquires the thread of execution represented by rhs(if any).
// If it is joinable, terminate() is called.
// After the call, rhs no longer represents any thread of execution(as if default - constructed).
std::thread threads[5]; // default-constructed threads
std::cout << "Spawning 5 threads...
";
for (int i = 0; i<5; ++i)
threads[i] = std::thread(pause_thread, i + 1); // move-assign threads
std::cout << "Done spawning threads. Now waiting for them to join:
";
for (int i = 0; i<5; ++i)
threads[i].join();
std::cout << "All threads joined!
";
return 0;
}
//////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/this_thread/sleep_for/
int test_this_thread_sleep_for()
{
// this_thread::sleep_for: Blocks execution of the calling thread during the span of time specified by rel_time.
// The execution of the current thread is stopped until at least rel_time has passed from now.
// Other threads continue their execution.
std::cout << "countdown:
";
for (int i = 10; i>0; --i) {
std::cout << i << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!
";
return 0;
}
/////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/this_thread/sleep_until/
int test_this_thread_sleep_until()
{
// this_thread::sleep_until: Blocks the calling thread until abs_time.
// The execution of the current thread is stopped until at least abs_time, while other threads may continue to advance.
using std::chrono::system_clock;
std::time_t tt = system_clock::to_time_t(system_clock::now());
struct std::tm * ptm = std::localtime(&tt);
#ifdef _MSC_VER
std::cout << "Current time: " << std::put_time(ptm, "%X") << '
';
#endif
std::cout << "Waiting for the next minute to begin...
";
++ptm->tm_min; ptm->tm_sec = 0;
std::this_thread::sleep_until(system_clock::from_time_t(mktime(ptm)));
#ifdef _MSC_VER
std::cout << std::put_time(ptm, "%X") << " reached!
";
#endif
return 0;
}
/////////////////////////////////////////////////////////////////
// reference: http://www.cplusplus.com/reference/thread/this_thread/yield/
std::atomic ready(false);
static void count1m(int id)
{
while (!ready) { // wait until main() sets ready...
std::this_thread::yield();
}
for (volatile int i = 0; i<1000000; ++i) {}
std::cout << id << std::endl;
}
int test_this_thread_yield()
{
// this_thread::yield: The calling thread yields, offering the implementation the opportunity to reschedule.
// This function shall be called when a thread waits for other threads to advance without blocking.
std::thread threads[10];
std::cout << "race of 10 threads that count to 1 million:
";
for (int i = 0; i<10; ++i) threads[i] = std::thread(count1m, i);
ready = true; // go!
for (auto& th : threads) th.join();
std::cout << '
';
return 0;
}
//////////////////////////////////////////////////////////////
// reference: https://zh.wikibooks.org/zh-hans/C%2B%2B/STL/Thread
template
class SyncQueue {
public:
SyncQueue(int maxSize) :m_maxSize(maxSize), m_needStop(false) {}
void Put(const T&x) { Add(x); }
void Put(T&&x) { Add(std::forward(x)); }
void Take(std::list& list)
{
std::unique_lock<:mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop) return;
list = std::move(m_queue);
m_notFull.notify_one();
}
void Take(T& t)
{
std::unique_lock<:mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop) return;
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
void Stop()
{
{
std::lock_guard<:mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
}
bool Empty()
{
std::lock_guard<:mutex> locker(m_mutex);
return m_queue.empty();
}
bool Full()
{
std::lock_guard<:mutex> locker(m_mutex);
return m_queue.size() == m_maxSize;
}
size_t Size()
{
std::lock_guard<:mutex> locker(m_mutex);
return m_queue.size();
}
int Count()
{
return m_queue.size();
}
private:
bool NotFull() const
{
bool full = m_queue.size() >= m_maxSize;
if (full)
std::cout << "full, waiting, thread id: " << std::this_thread::get_id() << std::endl;
return !full;
}
bool NotEmpty() const
{
bool empty = m_queue.empty();
if (empty)
std::cout << "empty,waiting, thread id: " << std::this_thread::get_id() << std::endl;
return !empty;
}
template
void Add(F&&x)
{
std::unique_lock< std::mutex> locker(m_mutex);
m_notFull.wait(locker, [this] {return m_needStop || NotFull(); });
if (m_needStop) return;
m_queue.push_back(std::forward(x));
m_notEmpty.notify_one();
}
private:
std::list m_queue; //
std::mutex m_mutex; //
std::condition_variable m_notEmpty;//
std::condition_variable m_notFull; //
int m_maxSize; // size
bool m_needStop; //
};
const int MaxTaskCount = 100;
class ThreadPool {
public:
using Task = std::function;
ThreadPool(int numThreads = std::thread::hardware_concurrency()) : m_queue(MaxTaskCount)
{
Start(numThreads);
}
~ThreadPool(void)
{
//
Stop();
}
void Stop()
{
std::call_once(m_flag, [this] {StopThreadGroup(); }); // StopThreadGroup
}
void AddTask(Task&&task)
{
m_queue.Put(std::forward(task));
}
void AddTask(const Task& task)
{
m_queue.Put(task);
}
private:
void Start(int numThreads)
{
m_running = true;
//
for (int i = 0; i (&ThreadPool::RunInThread, this));
}
}
void RunInThread()
{
while (m_running) {
//
std::list list;
m_queue.Take(list);
for (auto& task : list) {
if (!m_running)
return;
task();
}
}
}
void StopThreadGroup()
{
m_queue.Stop(); //
m_running = false; // false,
for (auto thread : m_threadgroup) { //
if (thread)
thread->join();
}
m_threadgroup.clear();
}
std::list<:shared_ptr>> m_threadgroup; //
SyncQueue m_queue; //
std::atomic_bool m_running; //
std::once_flag m_flag;
};
void TestThdPool()
{
ThreadPool pool; bool runing = true;
std::thread thd1([&pool, &runing] {
while (runing) {
std::cout << "produce " << std::this_thread::get_id() << std::endl;
pool.AddTask([] {
std::cout << "consume " << std::this_thread::get_id() << std::endl;
});
}
});
std::this_thread::sleep_for(std::chrono::seconds(10));
runing = false;
pool.Stop();
thd1.join();
getchar();
}
int test_thread_pool()
{
TestThdPool();
return 0;
}
//////////////////////////////////////////////////////////////
int test_thread_hardware_concurrency()
{
std::cout << " the number of hardware thread contexts: " << std::thread::hardware_concurrency() << std::endl;
return 0;
}
#endif
//////////////////////////////////////////////////////////////////
// reference: https://thispointer.com/c-11-multithreading-part-1-three-different-ways-to-create-threads/
// creating a thread using function objects
class DisplayThread {
public:
void operator()()
{
for (int i = 0; i < 10; ++i)
std::cout<
GitHub:https://github.com/fengbingchun/Messy_Test