'\" te .\" Copyright (c) 2008, 2014, Oracle and/or its affiliates.All rights reserved. .TH threads 5 "2014 年 4 月 23 日" "SunOS 5.11" "标准、环境和宏" .SH 名称 threads, pthreads \- POSIX pthread 和 Solaris 线程概念 .SH 用法概要 .SS "POSIX" .LP .nf cc –mt [ \fIflag\fR... ] \fIfile\fR... [ \fI library\fR... ] .fi .LP .nf #include .fi .SS "Solaris" .LP .nf cc –mt [ \fIflag\fR... ] \fIfile\fR... [ \fI library\fR... ] .fi .LP .nf #include .fi .LP .nf #include .fi .SH 描述 .sp .LP POSIX 和 Solaris 线程在 \fBlibc\fR(3LIB) 中均具有各自的实现。这两个实现可交互操作,其功能相似并可在同一应用程序中使用。只有 POSIX 线程保证可完全移植到符合 POSIX 的其他环境。POSIX 和 Solaris 线程需要不同的源,包括文件和链接系统信息库。请参见“用法概要”\fB\fR部分。 .SS "相似之处" .sp .LP 大部分 POSIX 和 Solaris 线程函数互相对应。POSIX 函数名称具有 “\fBpthread\fR” 前缀(信号名称除外)。相似的 POSIX 和 Solaris 函数的函数名称也具有相似的结尾。通常,相似的 POSIX 和 Solaris 函数的参数数目和用法相同。 .SS "不同之处" .sp .LP POSIX pthread 和 Solaris 线程的不同之处在于: .RS +4 .TP .ie t \(bu .el o POSIX 线程的可移植性更好。 .RE .RS +4 .TP .ie t \(bu .el o POSIX 线程根据可配置的属性对象为每个线程建立特性。 .RE .RS +4 .TP .ie t \(bu .el o POSIX pthread 实现了线程取消。 .RE .RS +4 .TP .ie t \(bu .el o POSIX pthread 强制执行调度算法。 .RE .RS +4 .TP .ie t \(bu .el o POSIX pthread 允许使用 \fBfork\fR(2) 调用的清理处理程序。 .RE .RS +4 .TP .ie t \(bu .el o 可暂停和继续执行 Solaris 线程。 .RE .RS +4 .TP .ie t \(bu .el o Solaris 线程实现守护进程线程,进程不会等待其终止。 .RE .SH 函数比较 .sp .LP 下表对 POSIX pthread 和 Solaris 线程函数进行了比较。当 POSIX pthread 或 Solaris 线程中没有可比较的接口时,列中会显示连字符 (\fB–\fR)。 .SS "与创建有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_create()\fR\fBthr_create()\fR \fBpthread_attr_init()\fR\fB–\fR \fBpthread_attr_setdetachstate()\fR\fB–\fR \fBpthread_attr_getdetachstate()\fR\fB–\fR \fBpthread_attr_setinheritsched()\fR\fB–\fR \fBpthread_attr_getinheritsched()\fR\fB–\fR \fBpthread_attr_setschedparam()\fR\fB–\fR \fBpthread_attr_getschedparam()\fR\fB–\fR \fBpthread_attr_setschedpolicy()\fR\fB–\fR \fBpthread_attr_getschedpolicy()\fR\fB–\fR \fBpthread_attr_setscope()\fR\fB–\fR \fBpthread_attr_getscope()\fR\fB–\fR \fBpthread_attr_setstackaddr()\fR\fB–\fR \fBpthread_attr_getstackaddr()\fR\fB–\fR \fBpthread_attr_setstacksize()\fR\fB–\fR \fBpthread_attr_getstacksize()\fR\fB–\fR \fBpthread_attr_getguardsize()\fR\fB–\fR \fBpthread_attr_setguardsize()\fR\fB–\fR \fBpthread_attr_destroy()\fR\fB–\fR \fB–\fR\fBthr_min_stack()\fR .TE .SS "与退出有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_exit()\fR\fBthr_exit()\fR \fBpthread_join()\fR\fBthr_join()\fR \fBpthread_detach()\fR\fB–\fR .TE .SS "与线程特定数据有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_key_create()\fR\fBthr_keycreate()\fR \fBpthread_setspecific()\fR\fBthr_setspecific()\fR \fBpthread_getspecific()\fR\fBthr_getspecific()\fR \fBpthread_key_delete()\fR\fB–\fR .TE .SS "与信号有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_sigmask()\fR\fBthr_sigsetmask()\fR \fBpthread_kill()\fR\fBthr_kill()\fR .TE .SS "与 ID 有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_self()\fR\fBthr_self()\fR \fBpthread_equal()\fR\fB–\fR \fB–\fR\fBthr_main()\fR .TE .SS "与调度有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fB–\fR\fBthr_yield()\fR \fB–\fR\fBthr_suspend()\fR \fB–\fR\fBthr_continue()\fR \fBpthread_setconcurrency()\fR\fBthr_setconcurrency()\fR \fBpthread_getconcurrency()\fR\fBthr_getconcurrency()\fR \fBpthread_setschedparam()\fR\fBthr_setprio()\fR \fBpthread_setschedprio()\fR\fBthr_setprio()\fR \fBpthread_getschedparam()\fR\fBthr_getprio()\fR .TE .SS "与取消有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_cancel()\fR\fB–\fR \fBpthread_setcancelstate()\fR\fB–\fR \fBpthread_setcanceltype()\fR\fB–\fR \fBpthread_testcancel()\fR\fB–\fR \fBpthread_cleanup_pop()\fR\fB–\fR \fBpthread_cleanup_push()\fR\fB–\fR .TE .SS "与互斥锁有关的函数" .sp .sp .TS tab(); lw(3.85i) lw(1.65i) lw(3.85i) lw(1.65i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_mutex_init()\fR\fBmutex_init()\fR \fBpthread_mutexattr_init()\fR\fB–\fR \fBpthread_mutexattr_setpshared()\fR\fB–\fR \fBpthread_mutexattr_getpshared()\fR\fB–\fR \fBpthread_mutexattr_setprotocol()\fR\fB–\fR \fBpthread_mutexattr_getprotocol()\fR\fB–\fR \fBpthread_mutexattr_setprioceiling()\fR\fB–\fR \fBpthread_mutexattr_getprioceiling()\fR\fB–\fR \fBpthread_mutexattr_settype()\fR\fB–\fR \fBpthread_mutexattr_gettype()\fR\fB–\fR \fBpthread_mutexattr_setrobust()\fR\fB–\fR \fBpthread_mutexattr_getrobust()\fR\fB–\fR \fBpthread_mutexattr_destroy()\fR\fB–\fR \fBpthread_mutex_setprioceiling()\fR\fB–\fR \fBpthread_mutex_getprioceiling()\fR\fB–\fR \fBpthread_mutex_lock()\fR\fBmutex_lock()\fR \fBpthread_mutex_trylock()\fR\fBmutex_trylock()\fR \fBpthread_mutex_unlock()\fR\fBmutex_unlock()\fR \fBpthread_mutex_destroy()\fR\fBmutex_destroy()\fR .TE .SS "与条件变量有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_cond_init()\fR\fBcond_init()\fR \fBpthread_condattr_init()\fR\fB–\fR \fBpthread_condattr_setpshared()\fR\fB–\fR \fBpthread_condattr_getpshared()\fR\fB–\fR \fBpthread_condattr_destroy()\fR\fB–\fR \fBpthread_cond_wait()\fR\fBcond_wait()\fR \fBpthread_cond_timedwait()\fR\fBcond_timedwait()\fR \fBpthread_cond_signal()\fR\fBcond_signal()\fR \fBpthread_cond_broadcast()\fR\fBcond_broadcast()\fR \fBpthread_cond_destroy()\fR\fBcond_destroy()\fR .TE .SS "与读取器/写入器锁定有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_rwlock_init()\fR\fBrwlock_init()\fR \fBpthread_rwlock_rdlock()\fR\fBrw_rdlock()\fR \fBpthread_rwlock_tryrdlock()\fR\fBrw_tryrdlock()\fR \fBpthread_rwlock_wrlock()\fR\fBrw_wrlock()\fR \fBpthread_rwlock_trywrlock()\fR\fBrw_trywrlock()\fR \fBpthread_rwlock_unlock()\fR\fBrw_unlock()\fR \fBpthread_rwlock_destroy()\fR\fBrwlock_destroy()\fR \fBpthread_rwlockattr_init()\fR\fB–\fR \fBpthread_rwlockattr_destroy()\fR\fB–\fR \fBpthread_rwlockattr_getpshared()\fR\fB–\fR \fBpthread_rwlockattr_setpshared()\fR\fB–\fR .TE .SS "与信号有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBsem_init()\fR\fBsema_init()\fR \fBsem_open()\fR\fB–\fR \fBsem_close()\fR\fB–\fR \fBsem_wait()\fR\fBsema_wait()\fR \fBsem_trywait()\fR\fBsema_trywait()\fR \fBsem_post()\fR\fBsema_post()\fR \fBsem_getvalue()\fR\fB–\fR \fBsem_unlink()\fR\fB–\fR \fBsem_destroy()\fR\fBsema_destroy()\fR .TE .SS "与 fork( ) 清理有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_atfork()\fR\fB–\fR .TE .SS "与限制有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fBpthread_once()\fR\fB–\fR .TE .SS "与调试有关的函数" .sp .sp .TS tab(); lw(2.75i) lw(2.75i) lw(2.75i) lw(2.75i) . \fBPOSIX\fR\fBSolaris\fR \fB–\fR\fBthr_stksegment()\fR .TE .SH 锁定 .SS "同步" .sp .LP 多线程行为是异步的,因此针对并发和并行处理进行了优化。由于线程(始终来自同一进程,有时来自多个进程)相互之间共享全局数据,因此无法保证它们对任何时间点的共享数据具有独占访问权限。要获得对共享数据的独占访问权限,需要在线程之间进行同步。POSIX 和 Solaris 均实现了四种同步机制:互斥锁、条件变量、读取器/写入器锁定(\fI优化的频繁读、少量写互斥锁\fR)以及信号。 .sp .LP 同步多个线程会大大降低线程并发性。同步的粒度越粗,即锁定的代码块越大,并发性就越小。 .SS "MT \fBfork()\fR" .sp .LP 如果线程程序调用 \fBfork\fR(2),它会隐式调用只复制调用线程的 \fBfork1\fR(2)。如果整个进程中还有任何待处理的互斥锁,则应用程序应在调用 \fBfork()\fR 之前调用 \fBpthread_atfork\fR(3C) 等待并获取这些互斥锁。 .SH 调度 .SS "POSIX 线程" .sp .LP Solaris 支持以下三种 POSIX 调度策略: .sp .ne 2 .mk .na \fB\fBSCHED_OTHER\fR\fR .ad .RS 15n .rt 传统分时调度策略。该策略基于分时 (timesharing, TS) 调度类。 .RE .sp .ne 2 .mk .na \fB\fBSCHED_FIFO\fR\fR .ad .RS 15n .rt 先入先出调度策略。如果不被更高优先级抢占,根据此策略调度的线程将会继续执行直至完成。此类线程属于实时 (real-time, RT) 调度类。调用进程必须在其有效集中声明 {\fBPRIV_PROC_PRIOCNTL\fR} 特权。 .RE .sp .ne 2 .mk .na \fB\fBSCHED_RR\fR\fR .ad .RS 15n .rt 循环调度策略。如果不被更高优先级抢占,根据此策略调度的线程将在系统确定的时段内执行。此类线程属于实时 (real-time, RT) 调度类,调用进程必须在其有效集中声明 {\fBPRIV_PROC_PRIOCNTL\fR} 特权。 .RE .sp .LP 除了上述 POSIX 指定的调度策略以外,Solaris 还支持以下调度策略: .sp .ne 2 .mk .na \fB\fBSCHED_IA\fR\fR .ad .RS 13n .rt 根据 \fBpriocntl\fR(2) 中所述的交互式类 (Inter-Active Class, IA) 策略调度线程。 .RE .sp .ne 2 .mk .na \fB\fBSCHED_FSS\fR\fR .ad .RS 13n .rt 根据 \fBpriocntl\fR(2) 中所述的公平份额类 (Fair-Share Class, FSS) 策略调度线程。 .RE .sp .ne 2 .mk .na \fB\fBSCHED_FX\fR\fR .ad .RS 13n .rt 根据 \fBpriocntl\fR(2) 中所述的固定优先级类 (Fixed-Priority Class, FSS) 策略调度线程。 .RE .SS "Solaris 线程" .sp .LP 唯一受支持的调度策略是 \fBSCHED_OTHER\fR,即基于 \fBTS\fR 调度类的分时。 .SH 错误 .sp .LP 在多线程应用程序中,当有其他线程调用 \fBforkall\fR(2) 时,将会从阻止的系统调用返回 \fBEINTR\fR。 .SH 用法 .SS "\fB-mt\fR 编译器选项" .sp .LP \fB-mt\fR 编译器选项会编译和链接多线程代码。它使用 -\fBD_REENTRANT\fR 编译源文件并适当扩大支持系统信息库集。 .SH 属性 .sp .LP 有关下列属性的说明,请参见 \fBattributes\fR(5): .sp .sp .TS tab() box; cw(2.75i) |cw(2.75i) lw(2.75i) |lw(2.75i) . 属性类型属性值 _ MT 级别MT-Safe、Fork 1-Safe .TE .SH 另请参见 .sp .LP \fBcrle\fR(1)、\fBfork\fR(2)、\fBpriocntl\fR(2)、\fBlibpthread\fR(3LIB)、\fBlibrt\fR(3LIB)、\fBlibthread\fR(3LIB)、\fBpthread_atfork\fR(3C)、\fBpthread_create\fR(3C)、\fBattributes\fR(5)、\fBprivileges\fR(5)、\fBstandards\fR(5) .sp .LP \fI《Oracle Solaris 11.3 Linkers and Libraries Guide》\fR