您的位置:首页 > 编程语言 > C语言/C++

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,确保只能被调用一次,正确的调用序列
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()函数在多线程环境中非常有用,原子操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息