UNIX环境C语言编程(18)-线程控制
2015-02-12 09:06
260 查看
1、线程属性
•int pthread_attr_init(pthread_attr_t *attr);
•int pthread_attr_destroy(pthread_attr_t *attr);
•涉及分离状态、堆栈起始地址、堆栈大小、警戒区域大小、并发级别
•设置/获取分离状态
•int pthread_attr_getdetachstate(const
pthread_attr_t *restrict
attr, int *detachstate);
•int pthread_attr_setdetachstate(pthread_attr_t *attr,
int detachstate);
2、同步对象的属性
•互斥体属性
•允许一个互斥体在多个进程间共享
•int pthread_mutexattr_getpshared(const
pthread_mutexattr_t *restrict
attr, int *restrict
pshared);
•int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
•int pthread_mutexattr_gettype(const
pthread_mutexattr_t *restrict
attr, int *restrict type);
•int pthread_mutexattr_settype(pthread_mutexattr_t *attr,
int type);
•对于PTHREAD_MUTEX_RECURSIVE类型,允许一个互斥体被同一个线程多次加锁
•读写锁属性:允许一个读写锁在多个进程间共享
•条件变量属性:允许一个条件变量在多个进程间共享
3、可重入-线程安全
•指函数可以同时被多个线程安全的调用
•注意不要在函数内使用静态数据
4、特定于线程的数据
•又称为线程私有数据
•创建一个key,确保只能被调用一次,正确的调用序列
•与key绑定地址
•void *pthread_getspecific(pthread_key_t key);
•int pthread_setspecific(pthread_key_t key,
const void *value);
5、cancel选项
•设置cancel状态,允许cancel或禁止cancel
•int pthread_setcancelstate(int state,
int *oldstate);
•设置cancel类型,延迟cancel或立即cancel
•int pthread_setcanceltype(int type,
int *oldtype);
•缺省为延迟cancel:cancel请求被暂时挂起,只有线程执行到某些特定的函数时,才能被cancel
•void pthread_testcancel(void);
// 增加一个cancel点
•立即cancel:允许线程被随时终止
6、线程与信号
•每个线程有自己的信号掩码,但是信号的处理动作是整个进程共享的
•信号只递交给单个线程,对于硬件故障或定时器信号,递交给对应的线程;其它信号,递交给一个随机的线程
•改变线程的信号屏蔽
•int pthread_sigmask(int how,
constsigset_t *restrict set,
sigset_t *restrict
oset);
•int sigwait(const
sigset_t *restrict set,
int *restrict
signop); //
等待信号发生
•int pthread_kill(pthread_t thread,
int signo);
// 想线程发送信号
•创建一个线程,专职处理信号
7、线程与fork
•fork后,子进程中只存在一个线程,同时继承了互斥体、读写锁、条件变量
•子进程需要清理继承的同步对象
•int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
8、线程与I/O
•pread()与pwrite()函数在多线程环境中非常有用,原子操作
•int pthread_attr_init(pthread_attr_t *attr);
•int pthread_attr_destroy(pthread_attr_t *attr);
•涉及分离状态、堆栈起始地址、堆栈大小、警戒区域大小、并发级别
•设置/获取分离状态
•int pthread_attr_getdetachstate(const
pthread_attr_t *restrict
attr, int *detachstate);
•int pthread_attr_setdetachstate(pthread_attr_t *attr,
int detachstate);
2、同步对象的属性
•互斥体属性
•允许一个互斥体在多个进程间共享
•int pthread_mutexattr_getpshared(const
pthread_mutexattr_t *restrict
attr, int *restrict
pshared);
•int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
•int pthread_mutexattr_gettype(const
pthread_mutexattr_t *restrict
attr, int *restrict type);
•int pthread_mutexattr_settype(pthread_mutexattr_t *attr,
int type);
•对于PTHREAD_MUTEX_RECURSIVE类型,允许一个互斥体被同一个线程多次加锁
•读写锁属性:允许一个读写锁在多个进程间共享
•条件变量属性:允许一个条件变量在多个进程间共享
3、可重入-线程安全
•指函数可以同时被多个线程安全的调用
•注意不要在函数内使用静态数据
4、特定于线程的数据
•又称为线程私有数据
•创建一个key,确保只能被调用一次,正确的调用序列
void destructor(void *); pthread_key_t key; pthread_once_t init_done = PTHREAD_ONCE_INIT; void thread_init(void) { err = pthread_key_create(&key, destructor); } int threadfunc(void *arg) { pthread_once(&init_done, thread_init); ... }
•与key绑定地址
•void *pthread_getspecific(pthread_key_t key);
•int pthread_setspecific(pthread_key_t key,
const void *value);
5、cancel选项
•设置cancel状态,允许cancel或禁止cancel
•int pthread_setcancelstate(int state,
int *oldstate);
•设置cancel类型,延迟cancel或立即cancel
•int pthread_setcanceltype(int type,
int *oldtype);
•缺省为延迟cancel:cancel请求被暂时挂起,只有线程执行到某些特定的函数时,才能被cancel
•void pthread_testcancel(void);
// 增加一个cancel点
•立即cancel:允许线程被随时终止
6、线程与信号
•每个线程有自己的信号掩码,但是信号的处理动作是整个进程共享的
•信号只递交给单个线程,对于硬件故障或定时器信号,递交给对应的线程;其它信号,递交给一个随机的线程
•改变线程的信号屏蔽
•int pthread_sigmask(int how,
constsigset_t *restrict set,
sigset_t *restrict
oset);
•int sigwait(const
sigset_t *restrict set,
int *restrict
signop); //
等待信号发生
•int pthread_kill(pthread_t thread,
int signo);
// 想线程发送信号
•创建一个线程,专职处理信号
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <pthread.h> int quitflag; /* set nonzero by thread */ sigset_t mask; pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t wait = PTHREAD_COND_INITIALIZER; void *thr_fn(void *arg) { int err, signo; for (;;) { err = sigwait(&mask, &signo); if (err != 0) printf("%d, %s\n", err, "sigwait failed"); switch (signo) { case SIGINT: printf("\ninterrupt\n"); break; case SIGQUIT: pthread_mutex_lock(&lock); quitflag = 1; pthread_mutex_unlock(&lock); pthread_cond_signal(&wait); return(0); default: printf("unexpected signal %d\n", signo); exit(1); } } } int main(void) { int err; sigset_t oldmask; pthread_t tid; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); if ((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0) printf("%d, %s\n", err, "SIG_BLOCK error"); err = pthread_create(&tid, NULL, thr_fn, 0); if (err != 0) printf("%d, %s\n", err, "can't create thread"); pthread_mutex_lock(&lock); while (quitflag == 0) pthread_cond_wait(&wait, &lock); pthread_mutex_unlock(&lock); /* SIGQUIT has been caught and is now blocked; do whatever */ quitflag = 0; /* reset signal mask which unblocks SIGQUIT */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) perror("SIG_SETMASK error"); exit(0); }
7、线程与fork
•fork后,子进程中只存在一个线程,同时继承了互斥体、读写锁、条件变量
•子进程需要清理继承的同步对象
•int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER; void prepare(void) { printf("preparing locks...\n"); pthread_mutex_lock(&lock1); pthread_mutex_lock(&lock2); } void parent(void) { printf("parent unlocking locks...\n"); pthread_mutex_unlock(&lock1); pthread_mutex_unlock(&lock2); } void child(void) { printf("child unlocking locks...\n"); pthread_mutex_unlock(&lock1); pthread_mutex_unlock(&lock2); } void *thr_fn(void *arg) { printf("thread started...\n"); pause(); return(0); } int main(void) { int err; pid_t pid; pthread_t tid; #if defined(BSD) || defined(MACOS) printf("pthread_atfork is unsupported\n"); #else if ((err = pthread_atfork(prepare, parent, child)) != 0) printf("%d, %s\n", err, "can't install fork handlers"); err = pthread_create(&tid, NULL, thr_fn, 0); if (err != 0) printf("%d, %s\n", err, "can't create thread"); sleep(2); printf("parent about to fork...\n"); if ((pid = fork()) < 0) perror("fork failed"); else if (pid == 0) /* child */ printf("child returned from fork\n"); else /* parent */ printf("parent returned from fork\n"); #endif exit(0); }
8、线程与I/O
•pread()与pwrite()函数在多线程环境中非常有用,原子操作
相关文章推荐
- UNIX环境高级编程学习之第十二章线程控制-可重入(线程安全)的getenv方法
- unix环境高级编程-线程控制(1)
- UNIX环境高级编程 第十二章:线程控制
- UNIX环境编程学习笔记(27)——多线程编程(二):控制线程属性
- UNIX环境高级编程(第12章 线程控制)
- UNIX环境高级编程学习之第十二章线程控制-以分离状态创建线程
- UNIX环境编程学习笔记(18)——进程管理之进程控制三部曲
- UNIX环境高级编程 第12章 线程控制
- UNIX环境编程学习笔记(18)——进程管理之进程控制三部曲
- UNIX环境C语言编程(7)-进程控制
- (十) 一起学 Unix 环境高级编程 (APUE) 之 线程控制
- Unix环境高级编程:进程控制-线程控制-僵尸进程
- unix环境高级编程-线程控制(2)
- UNIX环境编程学习笔记(27)——多线程编程(二):控制线程属性
- UNIX环境高级编程-第12章- 线程控制 - 一
- UNIX环境高级编程-第12章- 线程控制 - 二
- UNIX环境C语言编程(17)-线程
- UNIX环境高级编程(十二)线程控制
- UNIX环境高级编程——线程属性之并发度
- UNIX环境高级编程——线程与进程区别