Solaris
多线程
1.
线程
创建一个缺省的线程
缺省的线程的属性:
l
非绑定
l
未分离
l
一个缺省大小的堆栈
l
具有和父线程一样的优先级
用
phread_attr_init()
创建一个缺省的属性对象,
用属性对象创建一个线程
pthread_create(3T)
int pthread_create( pthread_t *tid, const pthread_attr_t *tattr, void *(*start_routine)(void*), void *arg );
#include<pthread.h>
pthread_attr_t tattr;
pthread_t tid;
extern void *start_routine(void *arg);
void *arg;
int ret;
/*default behavior*/
ret = pthread_create( &tid, NULL, start_routine, arg );
/*init with default attributes*/
ret = pthread_attr_init( &tattr );
/*default behavior specified*/
ret = pthread_create( &tid, &tattr, start_routine, arg );
tattr
中含有初始化线程所需的属性,值赋为
NULL
即缺省。
start_routine
是线程入口函数的起始地址。当
start_routine
返回时,相应的线程就结束了。线程结束时的退出状态值是
start_routine
函数用
phread_exit()
函数返回的返回值。当
pthread_create()
函数调用成功时,线程标识符保存在参数
tid
指针指向中。
返回值,
pthread_create()
成功后返回
0
,
EAGAIN
超过了某个限制,如
LWPs
过多。
EINVAL tattr
值非法。
创建子线程时,传给子线程的输入参数最好是
malloc()
返回的指针(这样的指针指向进程堆中的存储空间)或指向全局变量的指针,而不要是指向局部变量的指针。因为当子线程访问输入参数时,创建子线程的函数可能已结束,局部变量也就不存在了。
等待线程结束
pthread_join(3T)
int pthread_join( pthread_t tid, void **status );
#include<pthread.h>
pthread_t tid;
int ret;
int status;
/*waiting to join thread “tid” with status*/
ret = pthread_join( tid, &status );
/*waiting to join thread “tid” without status*/
ret = pthread_join( tid, NULL );
pthread_join()
会阻塞调用它的线程,直到参数
tid
指定的线程结束。
tid
指定的线程必须在当前进程中,且必须是非分离的。
status
接收指定线程终止时的返回状态码。
不能有多个线程等待同一个线程终止,否则返回错误码
ESRCH
当
pthread_join()
返回时,终止线程占用的堆栈等资源已被回收。
返回值:成功返回
0
ESRCH tid
指定的线程不是一个当前线程中合法且未分离的线程。
EDEADLK tid
指定的是当前线程。
EINVAL tid
非法。
分离一个线程
pthread_detach(3T)
将非分离线程设置为分离线程。
int pthread_detach( pthread_t tid );
#include<pthread.h>
pthread_t tid;
int ret;
ret = pthread_detach( tid );
该函数通知线程库,当线程终止以后,
tid
所指线程的内存可以被立即收回。
返回值:成功返回
0
EINVAL tid
所指线程不是一个合法线程。
ESRCH tid
指定的线程不是一个当前线程中合法且未分离的线程。
为线程数据创建一个键
多线程的
c
语言程序具有三种数据:局部变量,全局变量,线程数据(
TSD
)
TSD
类似于全局变量,但是线程私有的。
每个
TSD
都有个键同他相关联。
pthread_key_create(3T)
int pthread_key_create( pthread_key_t *key, void (*destructor)(*void) );
#include<pthread.h>
pthread_key_t key;
int ret;
/*key create without destructor*/
ret = pthread_key_create( &key, NULL );
/*key create with destructor*/
ret = pthread_key_destructor( &key, destructor );
该函数成功时,份配的建放在
key
中,必须保证
key
指向的内存区有效。
destructor
用来释放不再需要的内存。
返回值:成功返回
0
EAGAIN key
名字空间耗尽
ENOMEM
没有足够的内存空间创建一个新的键。
删除线程数据的键
pthread_key_delete(3T)
solaris
线程接口中没有该函数
int pthread_key_delete( pthread_key_t key );
#include<pthread.h>
pthread_key_t key;
int ret;
ret = pthread_key_delete( key );
在调用该函数之前,必须释放和本线程相关联的资源,
pthread_key_delete()
不会引发键的解析函数。
返回值:成功返回
0
EINVAL key
值非法
设置线程数据键
pthread_setspecific(3T)
设置和某个线程数据键绑定在一起的线程数据(一般是指针)
int pthread_setspecific( pthread_key_t key, const void *value );
#include<pthread.h>
pthread_key_t key;
void *value;
int ret;
ret = pthread_setspecific( key, value );
返回值:成功返回
0
ENOMEM
没有足够的虚拟内存
EINVAL key
值非法
pthread_setspecific()
不释放原来绑定在键上的内存,给一个键绑定新的指针时,必须释放原指针指向的内存,否则会发生内存泄漏。
获取线程数据键
pthread_getspecific(3T)
获取绑定在线程数据键上的值,并在指定的位置存储值
int pthread_getspecific( pthread_key_t key, void**value )
#include<pthread.h>
pthread_key_t key;
void *value;
pthread_getspecific( key, &value );
返回值:不返回错误码
取线程标识符
pthread_self(3T)
取当前线程的标识符
pthread_t pthread_self( void );
#include<pthread.h>
pthread_t tid;
tid = pthread_self();
返回值:当前线程标识符。
比较线程标识符
pthread_equal(3T)
int pthread_equal( pthread_t tid1, pthread_t tid2 );
#include<pthread.h>
pthread_t tid1,tid2
int ret;
ret = pthread_equal( tid1, tid2 );
返回值:如果
tid1
和
tid2
相同返回非零值,否则返回
0
。如果参数非法,返回值不可预知。
初始化线程
pthread_once(3T)
用来调用初始化函数,只有第一次调用有效。
int pthread_once( pthread_once_t *once_control, void(*init_routine)(void) );
#include<pthread.h>
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int ret;
ret = pthread_once( &once_control, init_routine );
once_control
界定了相应的初始化函数是否被调用过。
返回值:成功返回
0
EINVAL
某个参数为
NULL
出让当前线程对处理器的控制权
sched_yeild(3R)
把当前线程的优先权让给有相同或更高优先级的线程。
int sched_yeild( void );
#include<pthread.h>
int ret;
ret = sched_yeild();
返回值:成功返回
0
ENOSYS
当前版本不支持
sched_yield()
设置线程的优先级
pthread_setschedparam(3T)
int pthread_setschedparam( pthread_t tid, int policy, const struct sched_param *param );
#include<pthread.h>
pthread_t tid;
int ret;
struct sched_param param;
int priority;
/*sched_priority will be the priority of the thread*/
sched_param,sched_priority = priority;
/*only supported policy ,other will result in ENOTSUP*/
policy = SCHED_OTHER;
/*scheduling parameters of target thread*/
ret = pthread_setschedparam( tid, policy, ¶m );
返回值:成功返回
0
EINVAL
属性值非法
ENOTSUP
属性值在当前版本不支持
取线程的优先级
pthread_getschedparam(3T)
int pthread_getschedparam( pthread_t tid, int policy, struct schedparam *param );
#include<pthread.h>
pthread_t tid;
sched_param param;
int prioprity;
int policy;
int ret;
/*scheduling parameters of target thread*/
ret = pthread_getschedparam( tid, &policy, ¶m );
/*sched_priority contains the priority of the thread*/
priority = param.sched_priority;
返回值:成功返回
0
ESRCH tid
不是一个现存的线程。
向线程发信号
pthread_kill(3T)
int pthread_kill( pthread_t tid, int sig );
#include<pthread.h>
#include<signal.h>
int sig;
pthread_t tid;
int ret;
ret = pthread_kill( tid, sig );
tid
指定的线程必须和函数当前线程在同一个进程中。
sig
为
0
时,进行错误检查,不发送信号,往往被用来检查
tid
的合法性。
返回值:成功返回
0
EINVAL sig
不是合法信号量
ESRCH tid
不是当前进程中的线程
访问当前线程的信号掩码
pthread_sigmask(3T)
int pthread_sigmask( int how, const sigset_t *new, sigset_t *old );
#include<pthread.h>
#include<signal.h>
int ret;
sigset_t old, new;
ret = pthread_sigmask( SIG_SETMASK, &new, &old );
ret = pthread_sigmask( SIG_BLOCK, &new, &old );
ret = pthread_sigmask( SIG_UNBLOCK, &new, &old );
how
表示对当前信号掩码进行什么操作。
SIG_SETMASK
:在信号掩码中加入
new
信号集,
new
表示新增加的要屏蔽的信号。
SIG_BLOCK
:在信号掩码中删去
new
信号集,
new
表示新增加的不需再屏蔽的信号。
SIG_UNBLOCK
:用
new
信号集替换信号掩码,
new
表示所有需要屏蔽的信号。
当
new
为
NULL
时,无论
how
是什么,当前线程的信号掩码都不会改变。
旧的信号掩码保存在
old
中。
返回值:成功返回
0
EINVAL how
的值未定义
安全的复制
pthread_atfork(3T)
int pthread_atfork( void(*prepare)(void), void(*parent)(void), void(*child)(void) );
终止线程
pthread_exit(3T)
void pthread_exit(void *status);
#include<pthread.h>
int status;
pthread_exit( &status );
终止当前线程,所有绑定在线程键上的内存将释放。如果当前线程是未分离的,该线程的标识符和推出代码(
status
)被保留,直到其它线程用
pthread_join()
等待当前线程的终止。如果当前线程是分离的,
status
被忽略,线程标识符立即收回。
返回值:若
status
不为
NULL
,线程的退出代码被置为
status
指向的值。
一个线程可以用一下方式终止自身运行。
从线程的入口函数返回。
调用
pthread_exit()
用
POSIX
的
pthread_cancel()
退出可以用以下方式:
异步的
由线程库定义的一系列退出点
有应用程序定义的一系列退出点
退出点
由程序通过
pthread_testcancel()
建立
调用了
pthread_cond_wait()
或
pthread_cond_timedwait()
等待一个条件的线程
调用了
pthread_join()
等待另一个线程结束的线程。
被阻塞在
sigwait(2)
上的线程。
一些标准的库函数。
退出线程
pthread_cancel(3T)
int pthread_cancel( pthread_t thread );
#include<pthread.h>
pthread_t thread;
int ret;
ret = pthread_cancel ( thread ) ;
返回值:成功返回
0
ESRCH
无指定的线程。
允许或禁止退出
pthread_setcancelstate(3T)
缺省是允许退出的。
int pthread_setcancelstate( int state, int *oldstate );
#include<pthread.h>
int oldstate;
int ret;
/*enable*/
ret = pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, &oldstate );
/*disabled*/
ret = pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, &oldstate );
返回值:成功返回
0
EINVAL state
值非法
设置退出类型
pthread_setcanceltype(3T)
可以设置成延迟类型或异步类型。缺省是延迟类型。异步类型下,线程可以在执行中的任何时候被退出。
int pthread_setcanceltype( int type, int *oldtype );
#include<pthread.h>
int oldtype;
int ret;
/*deferred mode*/
ret = pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &oldtype );
/*async mode*/
ret = pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype );
返回值:成功返回
0
EINVAL state
值非法
创建退出点
pthread_testcancel(3T)
void pthread_testcancel( void );
#include<pthread.h>
pthread_testcancel();
只有当线程的退出状态是允许退出,退出类型是延迟类型时,有效。
没有返回值。
将一个善后处理函数推入退出堆栈
pthread_cleanup_push(3T)
pthread_cleanup_pop(3T)
void Pthread_cleanup_push( void(*routine)(void*), void *args );
void pthread_cleanup_pop( int execute );
#include<pthread.h>
/*push the handler “routine” on cleanup stack*/
pthread_cleanup_push( routine, arg );
/*pop the “func” out of cleanup stack and execute “func”*/
pthread_cleanup_pop( 1 );
/*pop the “func” and don’t execute “func”*/
pthread_cleanup_pop( 0 );
1.
线程属性
只能在线程创建时制定属性,不能在运行时改变它。
一旦属性对象被配置好,它在进程范围内都是有效的。
初始化属性
pthread_attr_init(3T)
初始化一个线程属性对象,属性值是缺省值,占用内存由线程库分配。
int pthread_attr_init( pthread_attr_t *tattr );
#include<pthread.h>
pthread_attr_t tattr;
int ret;
/*initialize an attribute to the default value*/
ret = pthread_attr_init( &tattr );
属性对象的缺省值:
scope
(线程域)
PTHREAD_SCOPE_PROCESS
Detachstate
(分离状态)
PTHREAD_CREATE_JOINABLE
Stackaddr
(堆栈地址)
NULL
Stacksize
(堆栈大小)
1Mb
priority
(优先级)
父进程优先级
Inheritsched
(继承调度优先级)
PTHREAD_INHERIT_SCHED
schedpolicy
(调度策略)
SCHED_OTHER
返回值:成功返回
0
ENOMEM
没有足够的内存初始化线程属性对象
释放属性对象
pthread_attr_destroy(3T)
int pthread_attr_destroy( pthread_attr_t *tattr );
#include<pthread.h>
pthread_attr_t tattr;
int ret;
ret = pthread_attr_destroy( &tattr );
返回值:成功返回
0
EINVAL tattr
值非法
设置分离状态
pthread_attr.setdetachstate(3T)
创建线程时,如果指定这个线程为分离线程,一旦这个线程终止,他的线程标识符和其他相关的资源可以立即被使用。如果不需要等待某个线程终止,可以把它设定为分离。
int pthread_attr_setdetachstate( pthread_attr_t *tattr, int detachstate );
#include<pthread.h>
pthread_attr_t tattr;
int ret;
/*set the thread detach state*/
ret = pthread_attr_setdetachstate( &tattr, PTHREAD_CREATE_DETACHED );
返回值:成功返回
0
EINVAL tattr
的值或
detachstate
的值非法
取分离状态
pthread_attr_getdetachstate(3T)
int pthread_attr_getdetachstate( const pthread_attr_t *tattr, int *detachstate );
#include<pthread.h>
pthread_attr_t tattr;
int detachstate;
int ret;
ret = pthread_attr_getdetachstate( &tattr, &detachstate );
返回值:成功返回
0
EINVAL tattr
的值或
detachstate
的值非法