C++11 多线程相关知识的学习

C++多线程类Thread(C++11)

  • C++11中std命名空间将Boost库中的Thread加入,Boost的多线程从准标准变为标准,这里将其用法整理复习,以demo的形式复习,还是喜欢看我自己写的东西,符合我的个人逻辑
  • 头文件为#include<thread>,通过std::thread应用。就以Hello thread开始吧,需要注意的是1,join()函数和detach()函数的区别,2,数据同步操作mutex(需包含include<mutex>):互斥锁

1、  普通函数多线程调用

(1)无参数函数

#include <thread>
#include <iostream>

void hello_thread() {
	std::cout << "Hello Thread!" << std::endl;
}

int main() {
	std::thread t1(hello_thread);  
	t1.join();  // 主线程等待子线程执行结束之后,才会执行下一步的操作
	std::cout << "Main here" << std::endl;
	getchar();
	return 0;
}

(2)有参数函数

#include <thread>
#include <iostream>

using namespace std;

int msum(int a, int b) {
    int c = a + b;
    cout << a << " + " << b << " = " << c << endl;
    return c;
}

int main() {
    std::thread t1(msum,1,2);
    t1.join();  // 主线程等待子线程执行结束之后,才会执行下一步的操作
    std::cout << "Main here" << std::endl;
    getchar();
    return 0;
}

2、在类内部创建线程

(1)类内部函数为静态函数

#include <thread>
#include <iostream>

using namespace std;

class HelloThread{
    public:
        static void hellothread(){
            cout << "Hello World, I‘m a thread " << endl;
        }
        static void start(){
            thread thread(hellothread);
            thread.join();
        }

};

int main(){
    HelloThread::start();
    getchar();
    return 0;
}
  • 在这里start()和hellothread()方法都必须是static方法。 

(2)在Singleton模式内部创建线程: 

3 、用类内部函数在类外部创建线程:

  • 非常普通的类,只是用多线程调用其内部的函数
#include <thread>
#include <iostream>

using namespace std;

class HelloWorld{
    public:
        void hello(int year){
            cout << "I am " << year << " years old!" << endl;
        }
};

int main(){
    HelloWorld obj;
    thread thrd(&HelloWorld::hello,&obj,26);
    thrd.join();
    getchar();
    return 0;
}

 join()和detach()的区别:

  • join()的作用前面已经提到,主线程等待子线程结束方可执行下一步(串行),detach()是的子线程放飞自我,独立于主线程并发执行,主线程后续代码段无需等待。看看效果:

(1)join()

#include <thread>
#include <iostream>

using namespace std;

void hello_thread() {
    std::cout << "Hello Thread!" << std::endl;
}

int msum(int a, int b) {
    int c = a + b;
    cout << a << " + " << b << " = " << c << endl;
    return c;
}

int main(){
    thread t1(hello_thread);//主线程等待子线程运行结束之后才可以执行下一步
    t1.join();
    thread t2(msum,2,3);
    t2.join();

    //主线程代码
    cout << "Main here " << endl;
    getchar();
    return 0;
}

(2)detach()

#include <thread>
#include <iostream>

using namespace std;

void hello_thread() {
    std::cout << "Hello Thread!" << std::endl;
}

int msum(int a, int b) {
    int c = a + b;
    cout << a << " + " << b << " = " << c << endl;
    return c;
}

int main(){
    thread t1(hello_thread);//主线程等待子线程运行结束之后才可以执行下一步
    t1.detach();
    thread t2(msum,2,3);
    t2.detach();

    //主线程代码
    cout << "Main here " << endl;
    getchar();
    return 0;
}

 数据同步(线程同时操作一个数据的安全性):

  • 执行单个线程,上锁、解锁,维护了线程的安全性,防止线程之间交叉执行

#include <thread>
#include <iostream>
#include <mutex>
using namespace std;
std::mutex mt;
int data1 = 1;

void addmethod(int a){
    mt.lock();
    data1 += a;
    cout << "add data = " << data1 << endl;
    mt.unlock();
}
void multi(int a){
    mt.lock();
    data1 *= a;
    cout << "multi data = " << data1 << endl;
    mt.unlock();
}
void hello_thread() {
    std::cout << "Hello Thread!" << std::endl;
}

int msum(int a, int b) {
    int c = a + b;
    cout << a << " + " << b << " = " << c << endl;
    return c;
}

int main(){
    thread t1(addmethod,2);
    thread t2(multi,2);

    t1.detach();
    t2.detach();
    getchar();
    return 0;
}

线程暂停

  • 从外部让线程暂停,会引发很多并发问题,此处不做引申。这大概也是std::thread并没有直接提供pause函数的原因。但有时线程在运行时,确实需要“停顿”一段时间怎么办呢?可以使用std::this_thread::sleep_for或std::this_thread::sleep_until
#include <thread>
#include <iostream>
#include <mutex>
#include <chrono>
#include <ratio>
using namespace std;
std::mutex mt;

void pausable(){
    //sleep 500毫秒
    this_thread::sleep_for(chrono::milliseconds(500));
    //sleep 到达指定的时间点
    this_thread::sleep_until(chrono::system_clock::now() + chrono::milliseconds(500));
}
int main(){
    std::thread thread1(pausable);
    thread1.join();
    return 0;
}

线程停止

  • 一般情况下当线程函数执行完成后,线程“自然”停止。但在std::thread中有一种情况会造成线程异常终止,那就是:析构。当std::thread实例析构时,如果线程还在运行,则线程会被强行终止掉,这可能会造成资源的泄漏,因此尽量在析构前join一下,以确保线程成功结束。
  • 如果确实想提前让线程结束怎么办呢?一个简单的方法是使用“共享变量”,线程定期地去检测该量,如果需要退出,则停止执行,退出线程函数。使用“共享变量”需要注意,在多核、多CPU的情况下需要使用“原子”操作。

参考链接

猜你喜欢

转载自blog.csdn.net/CHYabc123456hh/article/details/108864359