C++11多线程学习笔记(一)

Thread Class

进程与线程

进程(英语:process),是指计算机中已运行的程序。进程曾经是分时系统的基本运作单位。

线程(英语:thread)是操作系统能够进行运算调度的最小单位。大部分情况下,它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

以上摘自Wiki

\(std::thread定义于头文件 <thread>\)

构造函数

#include <iostream>
#include <utility>
#include <thread>
#include <chrono>
 
void f1(int n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 1 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
 
void f2(int& n)
{
    for (int i = 0; i < 5; ++i) {
        std::cout << "Thread 2 executing\n";
        ++n;
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}
 
class foo
{
public:
    void bar()
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 3 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};
 
class baz
{
public:
    void operator()()
    {
        for (int i = 0; i < 5; ++i) {
            std::cout << "Thread 4 executing\n";
            ++n;
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }
    }
    int n = 0;
};
 
int main()
{
    int n = 0;
    foo f;
    baz b;
    std::thread t1; // t1 不是线程
    std::thread t2(f1, n + 1); // 按值传递
    std::thread t3(f2, std::ref(n)); // 按引用传递
    std::thread t4(std::move(t3)); // t4 现在运行 f2() 。 t3 不再是线程
    std::thread t5(&foo::bar, &f); // t5 在对象 f 上运行 foo::bar()
    std::thread t6(std::ref(b)); // t6 在对象 b 上运行 baz::operator()
    std::thread t7([]{std::cout << "Thread 4 executing\n" << std::endl;})// 通过Lambda表达式创建
    t2.join();
    t4.join();
    t5.join();
    t6.join();
    std::cout << "Final value of n is " << n << '\n';
    std::cout << "Final value of foo::n is " << f.n << '\n';
    std::cout << "Final value of baz::n is " << b.n << '\n';
}
/*
Thread 1 executing
Thread 2 executing
Thread 3 executing
Thread 4 executing
Thread 3 executing
Thread 1 executing
Thread 2 executing
Thread 4 executing
Thread 2 executing
Thread 3 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 2 executing
Thread 1 executing
Thread 4 executing
Thread 3 executing
Thread 1 executing
Thread 2 executing
Thread 4 executing
Final value of n is 5
Final value of foo::n is 5
Final value of baz::n is 5
*/

以上摘自cppreference

成员类id

get_id() 返回线程的id

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


int main()
{
    thread t1([] {cout << "线程创建成功!" << endl;});
    cout << "线程id为:" << t1.get_id() << endl;   
    t1.join();
    return 0;
}
/*
线程id为:2
线程创建成功!
*/

成员函数

join

阻塞当前进程,直至join所指进程执行完毕,也就是只有等join里面的进程执行结束后才能执行join后面的语句

未加join阻塞线程

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

void func()
{
    for (int i = 1; i <= 5; ++ i)
        cout << i << endl; 
}

int main()
{
    thread t1(func);
    for (int i = 1; i <= 100000; ++ i);
    for (int i = 1; i <= 5; ++ i)
        cout << "永远嘀神!" << endl; 

    t1.join();
    return 0;
}

/*
永远嘀神!
永远嘀神!
1永远嘀神!

永远嘀神!2

永远嘀神!3

4
5
*/

由运行结果可看出func(子线程)main(主线程)同时运行

加了join之后

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

void func()
{
    for (int i = 1; i <= 5; ++ i)
        cout << i << endl; 
}

int main()
{
    thread t1(func);
    t1.join();
    for (int i = 1; i <= 100000; ++ i);
    for (int i = 1; i <= 5; ++ i)
        cout << "永远嘀神!" << endl; 
    return 0;
}
/*
1
2
3
4
5
永远嘀神!
永远嘀神!
永远嘀神!
永远嘀神!
永远嘀神!
*/

主线程等待子线程执行完再执行

再看一个例子

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

void func()
{
    using one_second = chrono::duration<double, ratio<1,1>>; 
    this_thread::sleep_for(one_second(3));
    cout << "线程创建成功" << endl; 
}

int main()
{
    thread t1(func);
    cout << "永远嘀神!" << endl; 
    return 0;
}

/*
永远嘀神!
terminate called without an active exception
*/

子线程在主线程结束是被强制终止。

detach

​ 被detach后的线程成为守护线程或者分离线程,该线程脱离主线程的管制,成为独立的一个线程,运行完后由操作系统回收

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

void func()
{
    // using one_second = chrono::duration<double, ratio<1,1>>; 
    // //this_thread::sleep_for(one_second(0.5));

    cout << "线程创建成功" << endl; 
}

int main()
{
    thread t1(func);
    t1.detach();
    cout << "永远嘀神!" << endl; 
    return 0;
}
/*
永远嘀神!
*/

joinable

判断线程是否结束

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    std::thread t;
    std::cout << "before starting, joinable: " << std::boolalpha << t.joinable()
              << '\n';
 
    t = std::thread(foo);
    std::cout << "after starting, joinable: " << t.joinable() 
              << '\n';
 
    t.join();
    std::cout << "after joining, joinable: " << t.joinable() 
              << '\n';
}
/*
before starting, joinable: false
after starting, joinable: true
after joining, joinable: false
*/

swap

交换两个thread的内容

#include <iostream>
#include <thread>
#include <chrono>
 
void foo()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
void bar()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
}
 
int main()
{
    using std::swap;
 
    std::thread t1(foo);
    std::thread t2(bar);
 
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
    std::cout << "thread 1 address: " << &t1 << std::endl;
    std::cout << "thread 2 address: " << &t2 << std::endl;
    swap(t1, t2);
 
    std::cout << "after std::swap(t1, t2):" << std::endl;
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
    std::cout << "thread 1 address: " << &t1 << std::endl;
    std::cout << "thread 2 address: " << &t2 << std::endl;
    swap(t1, t2);
 
    std::cout << "after t1.swap(t2):" << std::endl;
    std::cout << "thread 1 id: " << t1.get_id() << std::endl;
    std::cout << "thread 2 id: " << t2.get_id() << std::endl;
    std::cout << "thread 1 address: " << &t1 << std::endl;
    std::cout << "thread 2 address: " << &t2 << std::endl;
 
    t1.join();
    t2.join();
}
/*
thread 1 id: 2
thread 2 id: 3
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
after std::swap(t1, t2):
thread 1 id: 3
thread 2 id: 2
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
after t1.swap(t2):
thread 1 id: 2
thread 2 id: 3
thread 1 address: 0x6dfedc
thread 2 address: 0x6dfed8
*/

猜你喜欢

转载自www.cnblogs.com/niyada/p/12727531.html