C++线程之thread详解

 更新时间:2022年03月17日 10:43:38   作者:早睡的叶子  
这篇文章主要为大家详细介绍了C++线程中的thread,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

1.创建线程

直接初始话thread类对象进行创建线程,创建线程后调用join()方法,让主线程等待子线程完成工程。

#include <iostream>
#include <thread>
void thread_function()
{
    std::cout << "thread function\n";
}
int main()
{
    std::thread t(&thread_function);   // t starts running
    std::cout << "main thread\n";
    t.join();   // main thread waits for the thread t to finish
    return 0;
}

2.守护线程

我们可以调用detach()方法,将线程变为守护线程,完成线程和主线程的分离。一旦线程分离,我们不能强迫它再次加入主线程,再次调用join()方法会报错的。

一旦分离,线程应该永远以这种方式存在。调用join()函数之前可以使用函数joinable()检查线程是否可以加入主线程,加强程序健壮性。

// t2.cpp
int main()
{
    std::thread t(&thread_function);
    std::cout << "main thread\n";
    if( t.joinable( ) ) 
        // t.join();
    // t.join();
    t.detach();
    return 0;
}

3. 可调用对象

线程可以调用

  • 函数指针
  • 类对象
  • lamda表达式

1.函数指针

就像之前举例的样子

2.类对象

#include <iostream>
#include <thread>
class MyFunctor
{
public:
    void operator()() {
        std::cout << "functor\n";
    }
};
int main()
{
    MyFunctor fnctor;
    // 这样是不能运行的,
    // std::thread t(fnctor);
    // 必须按照这样进行初始话。
    // MyFunctor fnctor;  Note that we had to add () to enclose the MyFunctor(). 
    std::thread t((MyFunctor())); // it's related to the function declaration convention in C++.
    std::cout << "main thread\n";
    t.join();
    return 0;
}

3.lamda表达式

#include <iostream>
#include <thread>
class MyFunctor
{
public:
    void operator()() {
        std::cout << "functor\n";
    }
};
int main()
{
    MyFunctor fnctor;
    // 这样是不能运行的,
    // std::thread t(fnctor);
    // 必须按照这样进行初始话。
    // MyFunctor fnctor;  Note that we had to add () to enclose the MyFunctor(). 
    std::thread t((MyFunctor())); // it's related to the function declaration convention in C++.
    std::cout << "main thread\n";
    t.join();
    return 0;
}

4. 传参

传参分为三种

1.值传递

2.引用传递

3.不复制,也不共享内存的传参方式move()

#include <iostream>
#include <thread>
#include <string>
void thread_function(std::string s)
{
    std::cout << "thread function ";
    std::cout << "message is = " << s << std::endl;
}
int main()
{
    std::string s = "Kathy Perry";
    // 1. 值传递
    std::thread t(&thread_function, s);
    // 2. 引用传递
    std::thread t(&thread_function, std::ref(s));
    // 3. 不复制,也不共享内存的传参方式`move()
    std::thread t(&thread_function, std::move(s));
    std::cout << "main thread message = " << s << std::endl;
    t.join();
    return 0;
}

5. 线程的移动和复制

// t5.cpp
#include <iostream>
#include <thread>
void thread_function()
{
    std::cout << "thread function\n";
}
int main()
{
    std::thread t(&thread_function);
    std::cout << "main thread\n";
    //  transfer the ownership of the thread by moving it:
    std::thread t2 = move(t);
    t2.join();
    return 0;
}

6.线程id

获取线程的id: this_thread::get_id()

总共有多少个线程:std::thread::hardware_concurrency()

程序

int main()
{
    std::string s = "Kathy Perry";
    std::thread t(&thread_function, std::move(s));
    std::cout << "main thread message = " << s << std::endl;
    std::cout << "main thread id = " << std::this_thread::get_id() << std::endl;
    std::cout << "child thread id = " << t.get_id() << std::endl;
    t.join();
    return 0;
}

输出

thread function message is = Kathy Perry
main thread message =
main thread id = 1208
child thread id = 5224

7. 互斥mutex

互斥锁可能是 C++ 中使用最广泛的数据保护机制,但重要的是构造我们的代码以保护正确的数据并避免接口中固有的竞争条件。互斥锁也有自己的问题,表现为死锁和保护太多或太少的数据

标准 C++ 库提供了std::lock_guard类模板,它实现 了互斥锁的RAII习惯用法。它在构造时锁定提供的互斥锁并在销毁时解锁它,从而确保始终正确解锁锁定的互斥锁。

#include <iostream>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
using namespace std;
// a global variable
std::list<int>myList;
// a global instance of std::mutex to protect global variable
std::mutex myMutex;
void addToList(int max, int interval)
{
	// the access to this function is mutually exclusive
	std::lock_guard<std::mutex> guard(myMutex);
	for (int i = 0; i < max; i++) {
		if( (i % interval) == 0) myList.push_back(i);
	}
}
void printList()
{
	// the access to this function is mutually exclusive
	std::lock_guard<std::mutex> guard(myMutex);
	for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr ) {
		cout << *itr << ",";
	}
}
int main()
{
	int max = 100;
	std::thread t1(addToList, max, 1);
	std::thread t2(addToList, max, 10);
	std::thread t3(printList);
	t1.join();
	t2.join();
	t3.join();
	return 0;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!    

相关文章

  • C语言中main函数两个参数的作用

    C语言中main函数两个参数的作用

    这篇文章主要介绍了C语言中main函数两个参数的作用,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • C++中静态库与动态库的使用示例

    C++中静态库与动态库的使用示例

    在C/C++中使用库的技术,库主要分为两种类型:静态库和动态库,本文主要介绍了C++中静态库与动态库的使用示例,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • 一篇文章带你了解C++面向对象编程--继承

    一篇文章带你了解C++面向对象编程--继承

    这篇文章主要介绍了解析C++面对象编程--继承的运用,是C++入门学习中的基础知识,需要的朋友可以参考下,希望能够给你带来帮助
    2021-08-08
  • Qt 进度条的实现示例

    Qt 进度条的实现示例

    进度条在很多时候都可以用到,有时我们需要在表格,树状栏中直观显示任务进度或消耗百分比,本文就详细的介绍一下Qt 进度条的使用实例,感兴趣的可以了解一下
    2021-06-06
  • C语言零基础彻底掌握预处理下篇

    C语言零基础彻底掌握预处理下篇

    在C语言的程序中包括各种以符号#开头的编译指令,这些指令称为预处理命令。预处理命令属于C语言编译器,而不是C语言的组成部分,通过预处理命令可扩展C语言程序设计的环境
    2022-08-08
  • C++ Template 基础篇(一):函数模板详解

    C++ Template 基础篇(一):函数模板详解

    这篇文章主要介绍了C++ Template函数模板,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • C语言实现扫雷小程序

    C语言实现扫雷小程序

    这篇文章主要为大家详细介绍了C语言实现扫雷小程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • C++实现获取IP、子网掩码、网关、DNS等本机网络参数的方法

    C++实现获取IP、子网掩码、网关、DNS等本机网络参数的方法

    这篇文章主要介绍了C++实现获取IP、子网掩码、网关、DNS等本机网络参数的方法,需要的朋友可以参考下
    2014-07-07
  • C语言基础双指针移除元素解法

    C语言基础双指针移除元素解法

    这篇文章介绍了C语言基础双指针移除元素的解法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-12-12
  • C++用指针变量作为函数的参数接受数组的值的问题详细总结

    C++用指针变量作为函数的参数接受数组的值的问题详细总结

    以下是对C++中用指针变量作为函数的参数接受数组的值的问题进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10

最新评论