简介: 线程的创建和使用
菜鸟驿站
1 创建线程
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
e.g.
#include <iostream>
#include <stdio.h>
// 必须的头文件
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
// 线程的运行函数
void* say_hello(void* args)
{
printf("%s\n", (char *)args);
return 0;
}
int main()
{
// 定义线程的 id 变量,多个变量使用数组
pthread_t tids[NUM_THREADS];
char para_data[128] = "I am a sub thread";
for(int i = 0; i < NUM_THREADS; ++i)
{
//参数依次是:创建的线程id,线程参数,调用的函数,传入的函数参数
int ret = pthread_create(&tids[i], NULL, say_hello, (void *)para_data);
if (ret != 0)
{
cout << "pthread_create error: error_code=" << ret << endl;
}
}
//等各个线程退出后,进程才结束,否则进程强制结束了,线程可能还没反应过来;
pthread_exit(NULL);
}
# g++ thread_test.cpp -lpthread
打印结果: 略
1.1 线程传递单个参数
#include <iostream>
#include <cstdlib> //exit()
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
void* PrintHello(void* threadid)
{
// 对传入的参数进行强制类型转换,由无类型指针变为整形数指针,然后再读取
int tid = *((int*)threadid);
cout << "Hello Runoob! 线程 ID, " << tid << endl;
pthread_exit(NULL);
}
int main()
{
pthread_t threads[NUM_THREADS];
int para_data[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
cout << "main() : 创建线程, " << i << endl;
// 传入的时候必须强制转换为void* 类型,即无类型指针
para_data[i] = i;
int ret = pthread_create(&threads[i], NULL,
PrintHello, (void*)&(para_data[i]));
if (ret) {
cout << "Error:无法创建线程," << ret << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
打印结果
main() : 创建线程, 0
main() : 创建线程, 1
Hello Runoob! 线程 ID, 0
main() : 创建线程, 2
Hello Runoob! 线程 ID, 1
main() : 创建线程, 3
Hello Runoob! 线程 ID, 2
main() : 创建线程, 4
Hello Runoob! 线程 ID, 3
Hello Runoob! 线程 ID, 4
1.2 线程传递多个参数
通过结构体传递多个传输
创建指针不用初始化, 但是在使用的时候一定要指定某个空间. 否者会出现Segmentation fault (core dumped)
struct thread_data{
int thread_id;
char *message;
};
#include <iostream>
#include <cstdlib>
#include <pthread.h>
using namespace std;
#define NUM_THREADS 5
struct thread_data {
int thread_id;
char* message;
};
void* PrintHello(void* threadarg)
{
struct thread_data* my_data;
my_data = (struct thread_data*) threadarg;
cout << "Thread ID : " << my_data->thread_id;
cout << " Message : " << my_data->message << endl;
pthread_exit(NULL);
}
int main()
{
pthread_t threads[NUM_THREADS];
struct thread_data td[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
td[i].thread_id = i;
td[i].message = (char*)"This is message";
int ret = pthread_create(&threads[i], NULL,
PrintHello, (void*)&td[i]);
if (ret) {
cout << "Error:unable to create thread," << ret << endl;
exit(-1);
}
}
pthread_exit(NULL);
}
2 等待线程结束
NOTE: pthread_join通过阻塞的方式等待线程结束, 如果没有该函数, 则主线程很快结束从而整个进程结束, 从而使创建的线程没有机会开始执行就结束了.
线程链接和可分离: 创建的线程和进程一样, 也需要被连接以监听其推出状态, 否则也会变成僵尸线程. 退出后, 内核会保留退出状态数据, 直到取走为止. 处于分离状态的线程, 无法被任何线程执行连接获取其状态, 也无法再返回到可连接状态. 通常称呼分离线程
为守护线程(daemon threads)
int pthread_join(pthread_t thread, void **retval);
On success, pthread_join() returns 0; on error, it returns an error number.
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
using namespace std;
#define NUM_THREADS 5
void* wait(void* t)
{
int i;
long tid;
tid = (long)t;
sleep(1);
cout << "Sleeping in thread " << endl;
cout << "Thread with id : " << tid << " ...exiting " << endl;
pthread_exit(NULL);
}
int main()
{
int rc;
int i;
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
void* status;
// 初始化并设置线程为可连接的(joinable)
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < NUM_THREADS; i++) {
cout << "main() : creating thread, " << i << endl;
rc = pthread_create(&threads[i], NULL, wait, (void*)&i);
if (rc) {
cout << "Error:unable to create thread," << rc << endl;
exit(-1);
}
}
// 删除属性,并等待其他线程
pthread_attr_destroy(&attr);
for (i = 0; i < NUM_THREADS; i++) {
rc = pthread_join(threads[i], &status);
if (rc) {
cout << "Error:unable to join," << rc << endl;
exit(-1);
}
cout << "Main: completed thread id :" << i;
cout << " exiting with status :" << status << endl;
}
cout << "Main: program exiting." << endl;
pthread_exit(NULL);
}
3 线程库的使用
NOTE: c++11之后
hardware_concurrency(): 这个函数用于获取程序可以调动的最大线程数,在多核系统中可能代表CPU核数。这个函数返回值仅可以作为参考,因为有可能返回0。
thread t(hello);
t.join();
thread a(hello);
a.detach();
for (int i = 0; i < 5; ++i)
threads[i] = thread(pause_thread, i + 1);
for (auto& thread : threads)
thread.join();
# g++ thread_test.cpp -std=c++11 -lpthread
#include <iostream>
#include <thread>
using namespace std;
thread::id main_thread_id = this_thread::get_id();
void hello()
{
cout << "Hello Concurrent World\n";
if (main_thread_id == this_thread::get_id())
cout << "This is the main thread.\n";
else
cout << "This is not the main thread.\n";
}
void pause_thread(int n) {
this_thread::sleep_for(chrono::seconds(n));
cout << "pause of " << n << " seconds ended\n";
}
int main() {
thread t(hello);
cout << "data: "<<t.hardware_concurrency() << endl;//可以并发执行多少个(不准确)
//cout << "native_handle " << t.native_handle() << endl;//可以并发执行多少个(不准确)
t.join();
thread a(hello);
a.detach();
thread threads[5]; // 默认构造线程
cout << "Spawning 5 threads...\n";
for (int i = 0; i < 5; ++i)
threads[i] = thread(pause_thread, i + 1); // move-assign threads
cout << "Done spawning threads. Now waiting for them to join:\n";
for (auto& thread : threads)
thread.join();
cout << "All threads joined!\n";
}
技术交流QQ群:916932330(如有疑问或者技术问题请加群)