最简单的 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()
: 检查是否可joinjoin()
: 等待线程完成detach()
: 与该线程分离,一旦该线程执行完后它所分配的资源会被释放native_handle()
: 取得平台原生的native handle其他相关的常用函数有
sleep_for()
: 停止目前线程一段指定的时间yield()
: 暂时放弃CPU一段时间,让给其它线程以下例子为建立新 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 expressionstd::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元起,快前往官网查看详情吧