C++中的thread最全用法归纳-创新互联

基本 std::thread 的用法

最简单的 std::thread 范例如下所示,调用 thread 将立即同时开始执行这个新建立的线程,之后 main() 的主线程也会继续执行,基本上这就是一个基本的建立多线程的功能,详细说明请看后面的范例。

创新互联公司主营麦盖提网站建设的网络公司,主营网站建设方案,成都app开发,麦盖提h5小程序制作搭建,麦盖提网站营销推广欢迎麦盖提等地区企业咨询
#include#includevoid myfunc() {std::cout<< "myfunc\n";
    // do something ...
}

int main() {std::thread t1(myfunc);
    t1.join();
    return 0;
}
std::thread 常用的成员函数

以下为 c++ std::thread 常用的成员函数

  • get_id(): 取得目前的线程 id,回传一个为 std::thread::id 的类型
  • joinable(): 检查是否可join
  • join(): 等待线程完成
  • detach(): 与该线程分离,一旦该线程执行完后它所分配的资源会被释放
  • native_handle(): 取得平台原生的native handle

其他相关的常用函数有

  • sleep_for(): 停止目前线程一段指定的时间
  • yield(): 暂时放弃CPU一段时间,让给其它线程
范例1. 建立新 thread 执行函数

以下例子为建立新 c++ thread 来执行一个函数,其中 t1 是调用无参数的 foo() 函数,而 t2 线程是调用 bar() 有参数的函数

// g++ std-thread1.cpp -o a.out -std=c++11 -pthread
#include#includevoid foo() {std::cout<< "foo\n";
}

void bar(int x) {std::cout<< "bar\n";
}

int main() {std::thread t1(foo); // 建立一个新线程且执行 foo 函数
    std::thread t2(bar, 0); // 建立一個新线程且执行 bar 函数
    std::cout<< "main, foo and bar now execute concurrently...\n"; // synchronize threads

    std::cout<< "sleep 1s\n";
    std::this_thread::sleep_for(std::chrono::seconds(1));

    std::cout<< "join t1\n";
    t1.join(); // 等待 t1 线程结束
    std::cout<< "join t2\n";
    t2.join(); // 等待 t2 线程结束

    std::cout<< "foo and bar completed.\n";

    return 0;
}

输出

main, foo and bar now execute concurrently...
foo
bar
sleep 1s
join t1
join t2
foo and bar completed.

注意!在多线程中常常会互相对某函数或变量进行操作,需要对这些进行上锁,下一期将介绍,以确保同一时间只有某一个线程能进行存取

范例2. 建立新 thread 来执行一个类别中的函数

c++ std::thread 的构建可以传入 class 类别中的函数,如下范例所示

AA::start 分别建立 t1、t2 两个线程,而 t1 传入 AA::a1 类别函数,AA::a1 前面记得要加上&,第二参数代表的是哪个类别,之后的参数为传入函数所需的参数

// g++ std-thread2.cpp -o a.out -std=c++11 -pthread
#include#includeclass AA {public:
    void a1() {std::cout<< "a1\n";
    }

    void a2(int n) {std::cout<< "a2 "<< n<< "\n";
    }

    void start() {std::thread t1(&AA::a1, this);
        std::thread t2(&AA::a2, this, 10);

        t1.join();
        t2.join();
    }
};

int main() {AA a;
    a.start();

    return 0;
}

输出

a1
a2 10
范例3. 建立新 thread 来执行 lambda expression

std::thread 的构建也可以传入 lambda expression,如下范例所示

auto f = [](int n) {// Do Something
};
std::thread t1(f, 3);

也可以写成

std::thread t1([](int n) {// Do Something
};, 3);
范例4. join 等待 thread 执行结束

在 main 主线程建立 t1 线程后,主线程便继续往下执行,如果主线程需要等 t1 执行完毕后才能继续执行的话就需要使用 join,即等待 t1 线程执行完 foo 后主先线程才能继续执行,否则主线程会一直阻塞在 join 这一行

#include#include#includevoid foo() {this_thread::sleep_for(chrono::milliseconds(200));
    cout<<"foo";
}

int main() {std::thread t1(foo);
    cout<<"main 1";
    t1.join();
    cout<<"main 2";
    return 0;
}
范例5. detach 不等待 thread 执行结束

承上例,如果主线程不想等或是可以不用等待 t1 线程的话。就可以使用 detach 来让 t1 线程分离,接着主线程就可以继续执行,t1线程也在继续执行,在整个程序结束前最好养成好习惯确保所有子线程都已执行完毕,因为在 linux 系统如果主线程执行结束还有子线程在执行的话会报错

#include#include#includevoid foo() {this_thread::sleep_for(chrono::milliseconds(200));
    cout<<"foo";
}

int main() {std::thread t1(foo);
    cout<<"main 1";
    t1.detach();
    cout<<"main 2";
    return 0;
}
std::thread 用数组建立多个 thread
// g++ std-thread-array.cpp -o a.out -std=c++11 -pthread
#include#includevoid foo(int n) {std::cout<< "foo() "<< n<< "\n";
}

int main() {std::thread threads[3];

    for (int i = 0; i< 3; i++) {threads[i] = std::thread(foo, i);
    }

    for (int i = 0; i< 3; i++) {threads[i].join();
    }

    std::cout<< "main() exit.\n";

    return 0;
}

输出

foo() 1
foo() 0
foo() 2
main() exit.
std::thread 用 vector 建立多个 thread
// g++ std-thread-vector.cpp -o a.out -std=c++11 -pthread
#include#include#includevoid foo(int n) {std::cout<< "foo() "<< n<< std::endl;
}

int main() {std::vectorthreads;

    for (int i = 0; i< 3; i++) {threads.push_back(std::thread(foo, i));
    }

    for (int i = 0; i< 3; i++) {threads[i].join();
    }

    std::cout<< "main() exit.\n";

    return 0;
}
std::thread 参数传递使用传引用的方法

定义一个myfunc,其参数传递方式为传引用

void myfunc(int& n) {std::cout<< "myfunc n="<< n<< "\n";
    n+=10;
}

希望建立另外一个线程去执行 myfunc,之后需要取得这个 myfunc 的运算结果,但建立线程时如果写std::thread t1(myfunc, n);编译会出现错误,为什么会这样呢?

因为在 std::thread 的参数传递方式为传值,要传参考的话需要透过 std::ref 来辅助达成,所以就会写成这样,myfunc 与 myfunc2 的参数传递方式不同,可以看看这两者之间的差异

// g++ std-thread3.cpp -o a.out -std=c++11 -pthread
#include#includevoid myfunc(int& n) {std::cout<< "myfunc n="<< n<< "\n";
    n+=10;
}

void myfunc2(int n) {std::cout<< "myfunc n="<< n<< "\n";
    n+=10;
}
 
int main() {int n1 = 5;
    std::thread t1(myfunc, std::ref(n1));
    t1.join();
    std::cout<< "main n1="<< n1<< "\n";
    
    int n2 = 5;
    std::thread t2(myfunc2, n2);
    t2.join();
    std::cout<< "main n2="<< n2<< "\n";

    return 0;
}

输出

myfunc n=5
main n1=15
myfunc n=5
main n2=5

​下一期会教大家在多线程中使用 std::mutex进行上锁的用法与范例

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网页名称:C++中的thread最全用法归纳-创新互联
本文网址:http://azwzsj.com/article/ppjds.html