UNIX环境C语言编程(18)-线程控制

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, const sigset_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 () 函数在多线程环境中非常有用,原子操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值