• c++多线程基础1(thread)


    std::thread 在 <thread> 头文件中声明,因此使用 std::thread 时需要包含 <thread> 头文件。

    thread 构造函数:

    default (1)
    thread() noexcept;
    
    initialization (2)
    template <class Fn, class... Args>
    explicit thread (Fn&& fn, Args&&... args);
    
    copy [deleted] (3)
    thread (const thread&) = delete;
    
    move (4)
    thread (thread&& x) noexcept;

    (1). 默认构造函数,创建一个空的 thread 执行对象。

    (2). 初始化构造函数,创建一个 thread对象,该 thread 对象可被 joinable,新产生的线程会调用 fn 函数,该函数的参数由 args 给出。

    (3). 拷贝构造函数(被禁用),意味着 thread 不可被拷贝构造。

    (4). move 构造函数,move 构造函数,调用成功之后 x 不代表任何 thread 执行对象。

    注意:可被 joinable 的 thread 对象必须在他们销毁之前被主线程 join 或者将其设置为 detached.

    代码:

     1 #include <iostream>
     2 #include <chrono>
     3 #include <thread>
     4 using namespace std;
     5 
     6 void fun1(int n) {
     7     for(int i = 0; i < 5; ++i) {
     8         cout << "Thread " << n << " executing
    ";
     9         std::this_thread::sleep_for(std::chrono::milliseconds(10));
    10     }
    11 }
    12 
    13 void fun2(int &n) {
    14     for(int i = 0; i < 5; ++i) {
    15         cout << "Thread 2 executing
    ";
    16         ++n;
    17         std::this_thread::sleep_for(std::chrono::milliseconds(10));
    18     }
    19 }
    20 
    21 int main() {
    22     int n = 0;
    23     std::thread t1;//t1 不是一个线程
    24     std::thread t2(fun1, n + 1);//值传参
    25     std::thread t3(fun2, std::ref(n));//引用传参
    26     std::thread t4(std::move(t3));//将t3的资源转移到t4,此时t3不再是一个线程
    27 
    28     t2.join();
    29     t4.join();
    30 
    31     cout << "Final valuw of n is " << n << '
    ';
    32 
    33 // 输出:
    34 // Thread Thread 2 executing
    35 // 1 executing
    36 // Thread 2 executing
    37 // Thread 1 executing
    38 // Thread 2 executing
    39 // Thread 1 executing
    40 // Thread 2 executing
    41 // Thread 1 executing
    42 // Thread 2 executing
    43 // Thread 1 executing
    44 // Final valuw of n is 5
    45 
    46     return 0;
    47 }
    View Code

     

    拷贝赋值和移动赋值操作:

    move (1)
    thread& operator= (thread&& rhs) noexcept;
    
    copy [deleted] (2)
    thread& operator= (const thread&) = delete;

    (1). move 赋值操作,如果当前对象不可 joinable,需要传递一个右值引用(rhs)给 move 赋值操作;如果当前对象可被 joinable,则 terminate() 报错。

    (2). 拷贝赋值操作被禁用,thread 对象不可被拷贝

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void thread_task(int n) {
     7     std::this_thread::sleep_for(std::chrono::seconds(n));
     8     cout << "hello thread "
     9         << std::this_thread::get_id()
    10         << " paused " << n << " seconds" << endl;
    11 }
    12 
    13 int main(void) {
    14     std::thread thread[5];
    15     cout << "Spawning 5 threads...
    ";
    16     for(int i = 0; i < 5; ++i) {
    17         thread[i] = std::thread(thread_task, i + 1);//创建一个临时对象,并将临时对象资源移动到thread[i]
    18     }
    19     // thread[0] = thread[1];//错误,拷贝赋值函数是 delete 的
    20     cout << "Done wpawning threads! now wait fo them to join
    ";
    21     for(auto &t : thread) {
    22         t.join();
    23     }
    24     cout << "all threads joind.
    ";
    25 
    26 // 输出:
    27 // Spawning 5 threads...
    28 // Done wpawning threads! now wait fo them to join
    29 // hello thread 2 paused 1 seconds
    30 // hello thread 3 paused 2 seconds
    31 // hello thread 4 paused 3 seconds
    32 // hello thread 5 paused 4 seconds
    33 // hello thread 6 paused 5 seconds
    34 // all threads joind.
    35 
    36     return 0;
    37 }
    View Code

    成员函数 joinable:

    用于检测线程是否 joinable

    joinable : 代表该线程是可执行线程。

    not-joinable :通常一下几种情况会导致线程成为 not-joinable

         1) 由 thread 的缺省构造函数构造而成 (thread()没有参数)。

         2) 该 thread 被 move 过(包括 move 构造和 move 赋值)

         3) 该线程调用过 join 或者 detach

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void foo() {
     7     std::this_thread::sleep_for(std::chrono::seconds(1));
     8 }
     9 
    10 int main(void) {
    11     std::thread t;
    12     cout << t.joinable() << endl;//0
    13 
    14     t = std::thread(foo);//调用移动构造函数
    15     cout << t.joinable() << endl;//1
    16 
    17     t.join();
    18     cout << t.joinable() << endl;//0
    19 
    20     return 0;
    21 }
    View Code

    成员函数 get_id:

    标识与 *this 关联的线程的 std::thread::id 类型值。若无关联的线程,则返回默认构造的 std::thread::id 

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void foo() {
     7     std::this_thread::sleep_for(std::chrono::seconds(1));
     8 }
     9 
    10 int main(void) {
    11     std::thread t0;
    12     std::thread::id t0_id = t0.get_id();
    13 
    14     std::thread t1(foo);
    15     std::thread::id t1_id = t1.get_id();
    16 
    17     std::thread t2(foo);
    18     std::thread::id t2_id = t2.get_id();
    19 
    20     cout << "t0's id: " << t0_id << "
    ";
    21     cout << "t1's id: " << t1_id << "
    ";
    22     cout << "t2's id: " << t2_id << "
    ";
    23 
    24     t1.join();
    25     t2.join();
    26 
    27 // 输出:
    28 // t0's id: thread::id of a non-executing thread
    29 // t1's id: 2
    30 // t2's id: 3
    31     return 0;
    32 }
    View Code

    成员函数 native_handle:

    用于获得与操作系统相关的原生线程句柄

    代码:

     1 #include <thread>
     2 #include <mutex>
     3 #include <iostream>
     4 #include <chrono>
     5 #include <cstring>
     6 #include <pthread.h>
     7 using namespace std;
     8 
     9 std::mutex iomutex;
    10 
    11 void f(int num) {
    12     std::this_thread::sleep_for(std::chrono::seconds(1));
    13 
    14     sched_param sch;
    15     int policy;
    16     pthread_getschedparam(pthread_self(), &policy, &sch);
    17     std::lock_guard<std::mutex> lk(iostream);
    18     cout << "thread " << num << " is executing at priority "
    19         << sch.sched_priority << '
    ';
    20 }
    21 
    22 int main(void) {
    23     std::thread t1(f, 1), t2(f, 2);
    24  
    25     sched_param sch;
    26     int policy; 
    27     pthread_getschedparam(t1.native_handle(), &policy, &sch);
    28     sch.sched_priority = 20;
    29     if (pthread_setschedparam(t1.native_handle(), SCHED_FIFO, &sch)) {
    30         std::cout << "Failed to setschedparam: " << std::strerror(errno) << '
    ';
    31     }
    32 
    33     t1.join();
    34     t2.join();
    35 
    36     return 0;
    37 }
    View Code

    静态成员函数 hardware_concurrency:

    支持的并发线程数。若值非良定义或不可计算,则返回 0​ 

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 using namespace std;
     4 
     5 int main(void) {
     6     unsigned int n = std::thread::hardware_concurrency();
     7     cout << n << endl;//4
     8 
     9     return 0;
    10 }
    View Code

    成员函数 jion 和 detach:

    http://blog.csdn.net/xibeichengf/article/details/71173543

    当thread::join()函数被调用后,调用它的线程会被block,直到线程的执行被完成。基本上,这是一种可以用来知道一个线程已结束的机制。当thread::join()返回时,OS的执行的线程已经完成,C++线程对象可以被销毁

    当thread::detach()函数被调用后,执行的线程从线程对象中被分离,已不再被一个线程对象所表达--这是两个独立的事情。C++线程对象可以被销毁,同时OS执行的线程可以继续

    jion 样例代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <array>
     4 using namespace std;
     5 
     6 void show() {
     7     cout << "hello cplusplus
    ";
     8 }
     9 
    10 int main(void) {
    11     array<thread, 3> threads = {thread(show), thread(show), thread(show)};
    12     for(int i = 0; i < 3; ++i) {
    13         cout << threads[i].joinable() << endl;//判断当前线程是否可以 join
    14         threads[i].join();//主线程等待当前子线程完成才退出
    15     }
    16 
    17 // 输出:
    18 // hello cplusplus
    19 // 1hello cplusplus
    20 // hello cplusplus
    21 
    22 // 1
    23 // 1
    24 
    25     return 0;
    26 }
    View Code

    detach 样例代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void pause_thread(int n) {
     7     std::this_thread::sleep_for(std::chrono::seconds(n));
     8     cout << "pause of " << n << " seconds ended
    ";
     9 }
    10 
    11 int main(void) {
    12     cout << "Spawning and detaching 3 threads...
    ";
    13     std::thread(pause_thread, 1).detach();//将执行的线程从线程对象中被分离
    14     std::thread(pause_thread, 2).detach();
    15     std::thread(pause_thread, 3).detach();
    16     cout << "(the main thread will now pause for 5 seconds)
    ";
    17     pause_thread(5);
    18 
    19 // 输出:
    20 // Spawning and detaching 3 threads...
    21 // (the main thread will now pause for 5 seconds)
    22 // pause of 1 seconds ended
    23 // pause of 2 seconds ended
    24 // pause of 3 seconds ended
    25 // pause of 5 seconds ended
    26 
    27     return 0;
    28 }
    View Code

    注意:通常应该使用 join,除非你需要更灵活并且想要独立地提供一种同步机制来等待线程完成,在这种情况下你应该使用detach

    如果父线程先于子线程结束,那么子线程将在父线程结束的同时被迫结束

    thread::join() 会清理子线程相关的内存空间,此后 thread object 将不再和这个子线程相关了,即 thread object 不再 joinable 了,所以 join 对于一个子线程来说只可以被调用一次

    如果一个 C++ 线程对象当销毁时仍然可以被 join,会抛出异常

    成员函数 swap:

    void swap( thread& other noexcept;

    互换二个 thread 对象的底层句柄

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void foo() {
     7     std::this_thread::sleep_for(std::chrono::seconds(1));
     8 }
     9 
    10 void bar() {
    11     std::this_thread::sleep_for(std::chrono::seconds(1));
    12 }
    13 
    14 int main(void) {
    15     std::thread t1(foo);
    16     std::thread t2(bar);
    17 
    18     cout << t1.get_id() << endl;
    19     cout << t2.get_id() << endl;
    20 
    21     std::swap(t1, t2);
    22 
    23     cout << "===" << endl;
    24     cout << t1.get_id() << endl;
    25     cout << t2.get_id() << endl;
    26 
    27     t1.swap(t2);
    28 
    29     cout << "---" << endl;
    30     cout << t1.get_id() << endl;
    31     cout << t2.get_id() << endl;
    32 
    33     t1.join();
    34     t2.join();
    35 
    36 // 输出:
    37 // 2
    38 // 3
    39 // ===
    40 // 3
    41 // 2
    42 // ---
    43 // 2
    44 // 3
    45 
    46     return 0;
    47 }
    View Code

    std::swap

    void swap( thread &lhs, thread &rhs noexcept;

    为 std::thread 特化 std::swap 算法。交换 lhs 与 rhs 的状态。等效地调用 lhs.swap(rhs

    代码:

     1 #include <iostream>
     2 #include <thread>
     3 #include <chrono>
     4 using namespace std;
     5 
     6 void foo() {
     7     std::this_thread::sleep_for(std::chrono::seconds(1));
     8 }
     9 
    10 void bar() {
    11     std::this_thread::sleep_for(std::chrono::seconds(1));
    12 }
    13 
    14 int main(void) {
    15     std::thread t1(foo);
    16     std::thread t2(bar);
    17 
    18     cout << t1.get_id() << endl;
    19     cout << t2.get_id() << endl;
    20 
    21     std::swap(t1, t2);
    22 
    23     cout << "===" << endl;
    24     cout << t1.get_id() << endl;
    25     cout << t2.get_id() << endl;
    26 
    27     t1.swap(t2);
    28 
    29     cout << "---" << endl;
    30     cout << t1.get_id() << endl;
    31     cout << t2.get_id() << endl;
    32 
    33     t1.join();
    34     t2.join();
    35 
    36 // 输出:
    37 // 2
    38 // 3
    39 // ===
    40 // 3
    41 // 2
    42 // ---
    43 // 2
    44 // 3
    45 
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    mysql修改数据表名
    HDU 5742 It's All In The Mind (贪心)
    HDU 5752 Sqrt Bo (数论)
    HDU 5753 Permutation Bo (推导 or 打表找规律)
    HDU 5762 Teacher Bo (暴力)
    HDU 5754 Life Winner Bo (博弈)
    CodeForces 455C Civilization (并查集+树的直径)
    CodeForces 455B A Lot of Games (博弈论)
    CodeForces 455A Boredom (DP)
    HDU 4861 Couple doubi (数论 or 打表找规律)
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/8513800.html
Copyright © 2020-2023  润新知