1.1 第一个线程代码示例-线程创建示例
        多线程编程当中,每一个程序运行都至少会有一个线程,一般的main函数都作为主线程的入口,这里面是一个进程包含一个主线程,一个进程里面包含多个子线程,所以一般在主线程当中(也就是main函数中)再去启动一个子线程。
  
        需要包含头文件:#include <thread>
         用到的类:thread th(ThreadMain); 线程创建并启动
         阻塞等待函数:th.join();当子线程退出之后才解除阻塞
         如果不阻塞等待子线程退出的话,也就是把th.join();去掉,那么主线程运行完,就把th对象给销毁了,而这时子线程还在运行,这时就会弹窗报错。
  
         问题线程的话,是创建好,运行完回调函数就自动退出么?而主函数会把在内部创建的线程对象同时给销毁,也就是说应该先退出子线程再销毁线程对象。
#include <thread>
#include <iostream>
//Linux 中要链接动态库 -lpthread
using namespace std;
 
void ThreadMain()
{
    cout << "begin sub thread main " << this_thread::get_id() << endl; // get_id()获取当前线程ID
    for (int i = 0; i < 10; i++)
    {
        cout << "in thread " << i << endl;
        this_thread::sleep_for(chrono::seconds(1));//1000ms
    }
    cout << "end sub thread main " << this_thread::get_id() << endl;
}
int main(int argc, char* argv[])
{
    cout << "main thread ID " << this_thread::get_id() << endl;
    //线程创建并启动
    thread th(ThreadMain);
    cout << "begin wait sub thread  " << endl;
    //阻塞等待子线程退出
    th.join();
    cout << "end wait sub thread  " << endl;
    return 0;
} 
#编译
g++ -o main main3.c -lpthread 
结果:
 
线程的退出:我们这里创建了一个子线程,假如我们让他运行10s后再退出,这里就涉及到一个问题,假如里面是一个死循环,那么就会把单个CPU的资源耗尽,而有些任务处理的时候并不是计算任务,而只是在等待某一个结果,那么这个时候就可以在子线程中选择释放CPU资源,这里使用其中的一种方式,就是sleep,sleep就是当前线程释放CPU多长时间。
上面第8行和第21行,这两个打印输出可能是同时执行的,因为是多核并发,因此最后反应在屏幕上可能导致两行字叠在一块儿了。
1.2 thread对象生命周期和线程等待和分离

 
这里面导致错误的原因有多个,第一个首先是主线程退出了,那么我们先要保证主线程不要退出

但是结果还是跟上面一样。

我们希望主线程和子线程同时运行,然后我们又不想维护th这个对象(当然还有一种方式就是维护这个对象)那怎么办?
#include <thread>
#include <iostream>
//Linux -lpthread
using namespace std;
bool is_exit = false;//通过这个标志位通知子线程退出
 
void ThreadMain()
{
    cout << "begin sub thread main " << this_thread::get_id() << endl;
    for (int i = 0; i < 10; i++)
    {
        if (is_exit) break;
        cout << "in thread " << i << endl;
        this_thread::sleep_for(chrono::seconds(1));//1000ms
    }
    cout << "end sub thread main " << this_thread::get_id() << endl;
}
int main()
{
    {
        //thread th(ThreadMain);
        //th.detach();
        //主子线程分离,子线程就变成了在后台运行的线程,与主线程无关
        //坑:主线程退出后 子线程不一定退出,那造成一个什么现象,主线程退出之后,主线程的全局空间,
        //栈空间等全部都释放掉了,一旦子线程访问了这些空间,那么程序就会崩溃掉,在Windows中,写完程序
        //关闭的时候弹出一个错误窗口,那么多半是你还在运行的线程访问了静态成员变量或者全局变量,因为
        //变量都被销毁掉了,你还在访问它,那么就会出现错误。
    }
    {
        thread th(ThreadMain);
        this_thread::sleep_for(chrono::seconds(1));//1000ms
        is_exit = true; //通知子线程退出
        cout << "主线程阻塞,等待子线程退出" << endl;
        th.join(); //主线程阻塞,等待子线程退出
        cout << "子线程已经退出!" << endl;
    }
    //getchar();
    return 0;
} 
 
那么如何避免这样的情况呢?如果你用detach()函数分离了一个子线程,那么最后程序却崩溃了,那你的子线程就不要访问外部的变量了,就只访问线程函数内部的变量就行了,或者就是在主线程退出的时候通知一下我们,然后我们去退出,但是这种方式在实际问题中问题也比较多,所以大部分情况下不做detach了,而你又必须维系th这样的一个对象,不然你把对象删了,而子线程还在跑就会报错,那么我们就在整个程序析构的时候调用join函数就行了。
1.3 全局函数作为线程入口分析参数传递内存
#include <thread>
#include <iostream>
#include <string>
//Linux -lpthread
using namespace std;
class Para{
public:
    Para() { cout << "Create Para" << endl; }
    Para(const Para& p)
    {
        cout << "Copy Para" << endl;
        this->name = p.name;
    }
    ~Para() { cout << "Drop Para" << endl; }
    string name;
};
 
void ThreadMain(int p1, float p2, string str, Para p4){
    //延时100ms,确保f1被释放掉,因为此时主线程已经走到th.join();了
    //f1传过来后是拷贝,因此外部f1的销毁这里不受影响
    this_thread::sleep_for(100ms);
    cout << "ThreadMain " << p1 << " " << p2 << " " << str << " " << p4.name << endl;
}
 
int main(int argc, char* argv[]){
    thread th;
    //在栈空间中,一对大括号之后就会释放
    {
        //当这个f1释放之后,当调用thread创建线程这一行代码的时候,后面的参数都做了一份拷贝
        float f1 = 12.1f;
        Para p;
        p.name = "test Para class";
        //所有的参数做复制
        th = thread(ThreadMain, 101, f1, "test string para", p);
    }
    th.join();
    return 0;
} 
#编译
g++ -o main main3.c -lpthread 

这是Linux下的输出
 
这是Windows下VSstudio的输出,有点搞不明白两次结果为什么不一样,对Windows的结果解释:大括号中间创建一次,传递到thread函数拷贝构造一次,再次调用回调函数时候再次拷贝构造一次。所以一共创建了三次。所以使用值传递的方式会有很大的拷贝开销,应该多多考虑使用引用传递和指针传递。











![交换字符使得字符串相同[贪心]](https://img-blog.csdnimg.cn/2697794abadd4002bd7f0c3f9f4c2149.png)







