使用 C++11 编写 Linux 多线程程序(2)

如何创建和结束一个线程

和 pthread_create 不同,使用 thread 类创建线程可以使用一个函数作为入口,也可以是其它的 Callable 对象,而且,可以给入口传入任意个数任意类型的参数:

清单 2.例子 thread_run_func_var_args.cc

int funcReturnInt(const char* fmt, ...){ va_list ap; va_start(ap, fmt); vprintf( fmt, ap ); va_end(ap); return 0xabcd; } void threadRunFunction(void){ thread* t = new thread(funcReturnInt, "%d%s\n", 100, "\%"); t->join(); delete t; } 我们也可以传入一个 Lambda 表达式作为入口,比如:

清单 3.例子 thread_run_lambda.cc

void threadRunLambda(void){ int a = 100, b = 200; thread* t = new thread( [](int ia, int ib){ cout << (ia + ib) << endl; }, a, b ); t->join(); delete t; }

一个类的成员函数也可以作为线程入口:

清单 4.例子 thread_run_member_func.cc

struct God{ void create(const char* anything){ cout << "create " << anything << endl; } }; void threadRunMemberFunction(void){ God god; thread* t = new thread( &God::create, god, "the world" ); t->join(); delete t; }

虽然 thread 类的初始化可以提供这么丰富和方便的形式,其实现的底层依然是创建一个 pthread 线程并运行之,有些实现甚至是直接调用 pthread_create 来创建。

创建一个线程之后,我们还需要考虑一个问题:该如何处理这个线程的结束?一种方式是等待这个线程结束,在一个合适的地方调用 thread 实例的 join() 方法,调用者线程将会一直等待着目标线程的结束,当目标线程结束之后调用者线程继续运行;另一个方式是将这个线程分离,由其自己结束,通过调用 thread 实例的 detach() 方法将目标线程置于分离模式。一个线程的 join() 方法与 detach() 方法只能调用一次,不能在调用了 join() 之后又调用 detach(),也不能在调用 detach() 之后又调用 join(),在调用了 join() 或者 detach() 之后,该线程的 id 即被置为默认值(空线程),表示不能继续再对该线程作修改变化。如果没有调用 join() 或者 detach(),那么,在析构的时候,该线程实例将会调用 std::terminate(),这会导致整个进程退出,所以,如果没有特别需要,一般都建议在生成子线程后调用其 join() 方法等待其退出,这样子最起码知道这些子线程在什么时候已经确保结束。

在 C++11 里面没有提供 kill 掉某个线程的能力,只能被动地等待某个线程的自然结束,如果我们要主动停止某个线程的话,可以通过调用 Linux 操作系统提供的 pthread_kill 函数给目标线程发送信号来实现,示例如下:

清单 5.例子 thread_kill.cc

static void on_signal_term(int sig){ cout << "on SIGTERM:" << this_thread::get_id() << endl; pthread_exit(NULL); } void threadPosixKill(void){ signal(SIGTERM, on_signal_term); thread* t = new thread( [](){ while(true){ ++counter; } }); pthread_t tid = t->native_handle(); cout << "tid=" << tid << endl; // 确保子线程已经在运行。 this_thread::sleep_for( chrono::seconds(1) ); pthread_kill(tid, SIGTERM); t->join(); delete t; cout << "thread destroyed." << endl; }

上述例子还可以用来给某个线程发送其它信号,具体的 pthread_exit 函数调用的约定依赖于具体的操作系统的实现,所以,这个方法是依赖于具体的操作系统的,而且,因为在 C++11 里面没有这方面的具体约定,用这种方式也是依赖于 C++编译器的具体实现的。

linux

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/5fcf05c7c23c8234da980e853401e877.html