1. thread-join()
必要条件:添加 lthread 编译支持选项。
join()函数等待线程函数运行完毕,阻塞向下运行主函数;
#include <iostream>
#include <thread>
#include <unistd.h>
using namespace std;
void thread01(){
for (int i = 0; i < 5; i++){
cout << "Thread 01 is working !" << endl;
usleep(50000);
}
}
void thread02(){
for (int i = 0; i < 5; i++){
cout << "Thread 02 is working !" << endl;
usleep(80000);
}
}
int main() {
auto n = thread::hardware_concurrency();//获取cpu核心个数
cout << n << endl;
std::thread task01(thread01);
thread task02(thread02);
task01.join();
task02.join();
for (int i = 0; i < 5; i++){
cout << "Main thread is working !" << endl;
sleep(2);
}
system("pause");
}
2. thread-detach()
detach()函数不阻塞主线程;
#include <unistd.h>
#include <iostream>
#include <thread>
using namespace std;
void thread01() {
for (int i = 0; i < 5; i++) {
cout << "Thread 01 is working !" << endl;
sleep(1);
}
}
void thread02() {
for (int i = 0; i < 5; i++) {
cout << "Thread 02 is working !" << endl;
sleep(2);
}
}
int main() {
thread task01(thread01);
thread task02(thread02);
task01.detach();
task02.detach();
for (int i = 0; i < 5; i++) {
cout << "Main thread is working !" << endl;
sleep(3);
}
// system("pause");
// getchar();
}
3. 带参数的thread
在绑定的时候也可以同时给带参数的线程传入参数:
#include <unistd.h>
#include <iostream>
#include <thread>
using namespace std;
//定义带参数子线程
void thread01(int num) {
for (int i = 0; i < num; i++) {
cout << "Thread 01 is working !" << endl;
sleep(1);
}
}
void thread02(int num) {
for (int i = 0; i < num; i++) {
cout << "Thread 02 is working !" << endl;
sleep(2);
}
}
int main() {
thread task01(thread01, 5); //带参数子线程
thread task02(thread02, 5);
task01.detach();
task02.detach();
for (int i = 0; i < 5; i++) {
cout << "Main thread is working !" << endl;
sleep(3);
}
system("pause");
}
4. 多线程同步附加互斥锁mutex
多个线程同时对同一变量进行操作的时候,如果不对变量做一些保护处理,有可能导致处理结果异常或者漰溃结果如下:
#include <unistd.h>
#include <iostream>
#include <thread>
using namespace std;
int totalNum = 100;
void thread01() {
while (totalNum > 0) {
cout << totalNum << endl;
totalNum--;
sleep(1);
}
}
void thread02() {
while (totalNum > 0) {
cout << totalNum << endl;
totalNum--;
sleep(12);
}
}
int main() {
thread task01(thread01);
thread task02(thread02);
task01.detach();
task02.detach();
// system("pause");
}
第一个线程对变量操作的过程中,第二个线程也对同一个变量进行各操作,导致第一个线程处理完后的输出有可能是线程二操作的结果。针对这种数据竞争的情况,可以使用线程互斥对象mutex保持数据同步。mutex类的使用需要包含头文件mutex
#include <unistd.h>
#include <iostream>
#include <mutex>
#include <thread>
using namespace std;
mutex mu; //线程互斥对象
int totalNum = 10;
void thread01() {
while (totalNum > 0) {
mu.lock(); //同步数据锁
cout << totalNum << endl;
cout << "thread No.1" << endl;
totalNum--;
mu.unlock(); //解除锁定
sleep(1);
}
}
void thread02() {
while (totalNum > 0) {
mu.lock();
cout << totalNum << endl;
cout << "thread No.2" << endl;
totalNum -= 1;
mu.unlock();
sleep(1);
}
}
int main() {
thread task01(thread01);
thread task02(thread02);
task01.detach();
task02.join();
cout << "end line " << endl;
// system("pause");
}
加入互斥锁程序输出正常,其中sleep时间一定要打开互斥锁,要注意变量的可用空间时间。
使用lock_guard可以简化lock/unlock 的写法,同时也更安全,因为lock_guard在构造时会自动锁住互斥量,而在退出作用域后进行析构时就会自动解锁,从而避免忘了unlock操作
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex g_lock;//全局互斥锁对象,头文件#include <mutex>
void printer(const char *str)
{
//g_lock.lock();//上锁
lock_guard<mutex> locker(g_lock);//这里lock_guard代替了lock/unlock
while (*str!='\0')
{
cout << *str++;
this_thread::sleep_for(chrono::seconds(1));
}
cout << endl;
//g_lock.unlock();//解锁
}
//线程1
void func1()
{
const char *str = "hello";
printer(str);
}
//线程2
void func2()
{
const char *str = "world";
printer(str);
}
int main()
{
thread t1(func1);
thread t2(func2);
t1.join();
t2.join();
return 0;
}