`
brxonline
  • 浏览: 61680 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

UNIX编程(11)-线程

    博客分类:
  • C
 
阅读更多

1.线程标识

每个线程都有一个线程ID,线程ID只在它所属的进程环境有效

线程ID比较函数

 

#include <pthread.h>

int pthread_equal(pthread_t tid1, pthread_t tid2);

 

Returns: nonzero if equal, 0 otherwise

线程获得自身ID函数

 

 

#include <pthread.h>

pthread_t pthread_self(void);

 

Returns: the thread ID of the calling thread

 

 

2.线程创建

 

#include <pthread.h>

int pthread_create(pthread_t *restrict tidp,
                   const pthread_attr_t *restrictattr,
                   void *(*start_rtn)(void), void
 *restrict arg);

 

Returns: 0 if OK, error number on failure

当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID,新创建的线程从start_rtn函数的地址开始运行

例:打印线程ID

#include "apue.h"
#include <pthread.h>

pthread_t ntid;

void
printids(const char *s)
{
    pid_t      pid;
    pthread_t  tid;

    pid = getpid();
    tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid,
      (unsigned int)tid, (unsigned int)tid);
}

void *
thr_fn(void *arg)
{
    printids("new thread: ");
    return((void *)0);
}

int
main(void)
{
    int     err;

    err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0)
        err_quit("can't create thread: %s\n", strerror(err));
    printids("main thread:");
    sleep(1);
    exit(0);
}


3.线程终止

单个线程可以通过下列三种方式退出

1)线程只是从启动例程中返回,返回值是线程的退出码

2)线程可以被同一进程中的其他线程取消

3)线程调用pthread_exit

 

 

 

#include <pthread.h>

void pthread_exit(void *rval_ptr);

 


rval_ptr ,进程中的其他线程可以通过调用pthread_join函数访问到这个指针

 

 

#include <pthread.h>

int pthread_join(pthread_t thread, void **rval_ptr);

 

Returns: 0 if OK, error number on failure

调用pthread_join的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。

 

例:获得线程退出状态

 

#include "apue.h"
#include <pthread.h>

void *
thr_fn1(void *arg)
{
    printf("thread 1 returning\n");
    return((void *)1);
}

void *
thr_fn2(void *arg)
{
    printf("thread 2 exiting\n");
    pthread_exit((void *)2);
}

int
main(void)
{
    int         err;
    pthread_t   tid1, tid2;
    void        *tret;

    err = pthread_create(&tid1, NULL, thr_fn1, NULL);
    if (err != 0)
        err_quit("can't create thread 1: %s\n", strerror(err));
    err = pthread_create(&tid2, NULL, thr_fn2, NULL);
    if (err != 0)
        err_quit("can't create thread 2: %s\n", strerror(err));
    err = pthread_join(tid1, &tret);
    if (err != 0)
        err_quit("can't join with thread 1: %s\n", strerror(err));
    printf("thread 1 exit code %d\n", (int)tret);
    err = pthread_join(tid2, &tret);
    if (err != 0)
        err_quit("can't join with thread 2: %s\n", strerror(err));
    printf("thread 2 exit code %d\n", (int)tret);
    exit(0);
}

 

线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程,只是发出请求,不是终止

 

 

 

#include <pthread.h>

int pthread_cancel(pthread_t tid);

 

Returns: 0 if OK, error number on failure

 

线程可以安排它退出时需要调用的函数

#include <pthread.h>

void pthread_cleanup_push(void (*rtn)(void *),
 void *arg);

void pthread_cleanup_pop(int execute);

 

 


线程执行以下动作时调用清理函数

1)调用pthread_exit

2)响应取消请求

3)用非0execute参数调用 pthread_cleanup_pop时

例:线程清理处理程序

#include "apue.h"
#include <pthread.h>

void
cleanup(void *arg)
{
    printf("cleanup: %s\n", (char *)arg);
}

void *
thr_fn1(void *arg)
{
    printf("thread 1 start\n");
    pthread_cleanup_push(cleanup, "thread 1 first handler");
    pthread_cleanup_push(cleanup, "thread 1 second handler");
    printf("thread 1 push complete\n");
    if (arg)
        return((void *)1);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    return((void *)1);
}

void *
thr_fn2(void *arg)
{
    printf("thread 2 start\n");
    pthread_cleanup_push(cleanup, "thread 2 first handler");
    pthread_cleanup_push(cleanup, "thread 2 second handler");
    printf("thread 2 push complete\n");
    if (arg)
        pthread_exit((void *)2);
    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
    pthread_exit((void *)2);
}

int
main(void)
{
    int         err;
    pthread_t   tid1, tid2;
    void        *tret;

    err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);
    if (err != 0)
        err_quit("can't create thread 1: %s\n", strerror(err));
    err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);
    if (err != 0)
        err_quit("can't create thread 2: %s\n", strerror(err));
    err = pthread_join(tid1, &tret);
      if (err != 0)
        err_quit("can't join with thread 1: %s\n", strerror(err));
    printf("thread 1 exit code %d\n", (int)tret);
    err = pthread_join(tid2, &tret);
    if (err != 0)
        err_quit("can't join with thread 2: %s\n", strerror(err));
    printf("thread 2 exit code %d\n", (int)tret);
    exit(0);
}

 使用pthread_detach调用可以用于使线程进入分离状态(另外一种方式是修改创建进程时的属性)

 

#include <pthread.h>

int pthread_detach(pthread_t tid);

 

Returns: 0 if OK, error number on failure


4.线程同步

 1)互斥量

 

#include <pthread.h>

int pthread_mutex_init(pthread_mutex_t *restrict
mutex,
                       const pthread_mutexattr_t
 *restrict attr);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

 

Both return: 0 if OK, error number on failure

 

 

#include <pthread.h>

int pthread_mutex_lock(pthread_mutex_t *mutex);

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

 

All return: 0 if OK, error number on failure


例:使用互斥量的数据结构

#include <stdlib.h>
#include <pthread.h>

struct foo {
    int             f_count;
    pthread_mutex_t f_lock;
    /* ... more stuff here ... */
};

struct foo *
foo_alloc(void) /* allocate the object */
{
    struct foo *fp;

    if ((fp = malloc(sizeof(struct foo))) != NULL) {
        fp->f_count = 1;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
            free(fp);
            return(NULL);
        }
        /* ... continue initialization ... */
    }
    return(fp);
}

void
foo_hold(struct foo *fp) /* add a reference to the object */
{
    pthread_mutex_lock(&fp->f_lock);
    fp->f_count++;
    pthread_mutex_unlock(&fp->f_lock);
}

void
foo_rele(struct foo *fp) /* release a reference to the object */
{
    pthread_mutex_lock(&fp->f_lock);
    if (--fp->f_count == 0) { /* last reference */
        pthread_mutex_unlock(&fp->f_lock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
    } else {
        pthread_mutex_unlock(&fp->f_lock);
    }
}


例:避免死锁

#include <stdlib.h>
#include <pthread.h>

#define NHASH 29
#define HASH(fp) (((unsigned long)fp)%NHASH)

struct foo *fh[NHASH];
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;

struct foo {
    int             f_count; /* protected by hashlock */
    pthread_mutex_t f_lock;
    struct foo     *f_next; /* protected by hashlock */
    int             f_id;
    /* ... more stuff here ... */
};

struct foo *
foo_alloc(void) /* allocate the object */
{
    struct foo  *fp;
    int         idx;

    if ((fp = malloc(sizeof(struct foo))) != NULL) {
        fp->f_count = 1;
        if (pthread_mutex_init(&fp->f_lock, NULL) != 0) {
            free(fp);
            return(NULL);
        }
        idx = HASH(fp);
        pthread_mutex_lock(&hashlock);
        fp->f_next = fh[idx];
        fh[idx] = fp->f_next;
        pthread_mutex_lock(&fp->f_lock);
        pthread_mutex_unlock(&hashlock);
        /* ... continue initialization ... */
    }
    return(fp);

}

void
foo_hold(struct foo *fp) /* add a reference to the object */
{
    pthread_mutex_lock(&hashlock);
    fp->f_count++;
    pthread_mutex_unlock(&hashlock);
}

struct foo *
foo_find(int id) /* find a existing object */
{
    struct foo  *fp;
    int         idx;

    idx = HASH(fp);
    pthread_mutex_lock(&hashlock);
    for (fp = fh[idx]; fp != NULL; fp = fp->f_next) {
        if (fp->f_id == id) {
            fp->f_count++;
            break;
        }
    }
    pthread_mutex_unlock(&hashlock);
    return(fp);
}

void
foo_rele(struct foo *fp) /* release a reference to the object */
{
    struct foo  *tfp;
    int         idx;

    pthread_mutex_lock(&hashlock);
    if (--fp->f_count == 0) { /* last reference, remove from list */
        idx = HASH(fp);
        tfp = fh[idx];
        if (tfp == fp) {
            fh[idx] = fp->f_next;

        } else {
            while (tfp->f_next != fp)
                tfp = tfp->f_next;
            tfp->f_next = fp->f_next;
        }
        pthread_mutex_unlock(&hashlock);
        pthread_mutex_destroy(&fp->f_lock);
        free(fp);
    } else {
        pthread_mutex_unlock(&hashlock);
    }
}

 2)读写锁

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t *restrict
rwlock,
                        const pthread_rwlockattr_t
 *restrict attr);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

 

Both return: 0 if OK, error number on failure


 

#include <pthread.h>

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

 

All return: 0 if OK, error number on failure


#include <pthread.h>

int pthread_rwlock_tryrdlock(pthread_rwlock_t
 *rwlock);

int pthread_rwlock_trywrlock(pthread_rwlock_t
 *rwlock);

 

Both return: 0 if OK, error number on failure


例:使用读写锁
#include <stdlib.h>
#include <pthread.h>

struct job {
    struct job *j_next;
    struct job *j_prev;
    pthread_t   j_id;   /* tells which thread handles this job */
    /* ... more stuff here ... */
};

struct queue {
    struct job      *q_head;
    struct job      *q_tail;
    pthread_rwlock_t q_lock;
};

/*
* Initialize a queue.
*/
int
queue_init(struct queue *qp)
{
    int err;

    qp->q_head = NULL;
    qp->q_tail = NULL;
    err = pthread_rwlock_init(&qp->q_lock, NULL);
    if (err != 0)
        return(err);

    /* ... continue initialization ... */

    return(0);
}

/*
 * Insert a job at the head of the queue.
 */
void
job_insert(struct queue *qp, struct job *jp)
{
    pthread_rwlock_wrlock(&qp->q_lock);
    jp->j_next = qp->q_head;
    jp->j_prev = NULL;
    if (qp->q_head != NULL)
        qp->q_head->j_prev = jp;
    else
        qp->q_tail = jp;      /* list was empty */
    qp->q_head = jp;
    pthread_rwlock_unlock(&qp->q_lock);
}

/*
 * Append a job on the tail of the queue.
 */
void
job_append(struct queue *qp, struct job *jp)
{
    pthread_rwlock_wrlock(&qp->q_lock);
    jp->j_next = NULL;
    jp->j_prev = qp->q_tail;
    if (qp->q_tail != NULL)
        qp->q_tail->j_next = jp;
    else
        qp->q_head = jp;   /* list was empty */
    qp->q_tail = jp;
    pthread_rwlock_unlock(&qp->q_lock);
}

/*
 * Remove the given job from a queue.
 */
void
job_remove(struct queue *qp, struct job *jp)
{
    pthread_rwlock_wrlock(&qp->q_lock);
    if (jp == qp->q_head) {
        qp->q_head = jp->j_next;
        if (qp->q_tail == jp)
            qp->q_tail = NULL;
    } else if (jp == qp->q_tail) {
        qp->q_tail = jp->j_prev;
        if (qp->q_head == jp)
            qp->q_head = NULL;
    } else {
        jp->j_prev->j_next = jp->j_next;
        jp->j_next->j_prev = jp->j_prev;
    }
    pthread_rwlock_unlock(&qp->q_lock);
}
/*
 * Find a job for the given thread ID.
 */
struct job *
job_find(struct queue *qp, pthread_t id)
{
    struct job *jp;

    if (pthread_rwlock_rdlock(&qp->q_lock) != 0)
        return(NULL);

    for (jp = qp->q_head; jp != NULL; jp = jp->j_next)
         if (pthread_equal(jp->j_id, id))
             break;

    pthread_rwlock_unlock(&qp->q_lock);
    return(jp);
}


3)条件变量

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *restrict cond,
                      pthread_condattr_t *restrict
attr);

int pthread_cond_destroy(pthread_cond_t *cond);

 

Both return: 0 if OK, error number on failure


#include <pthread.h>

int pthread_cond_wait(pthread_cond_t *restrict cond,
                      pthread_mutex_t *restrict
mutex);

int pthread_cond_timedwait(pthread_cond_t
 *restrict cond,
                           pthread_mutex_t
 *restrict mutex,
                           const struct timespec
 *restrict timeout);

 

Both return: 0 if OK, error number on failure


例:使用条件变量
#include <pthread.h>

struct msg {
    struct msg *m_next;
    /* ... more stuff here ... */
};
struct msg *workq;
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;

void
process_msg(void)
{
    struct msg *mp;

    for (;;) {
        pthread_mutex_lock(&qlock);
        while (workq == NULL)
            pthread_cond_wait(&qready, &qlock);
        mp = workq;
        workq = mp->m_next;
        pthread_mutex_unlock(&qlock);
        /* now process the message mp */
    }
}

void
enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);
}

 

分享到:
评论

相关推荐

    linux编程技术-多线程-网络编程

    下载于北大未名BBS精华区 内容:UNIX环境高级编程,Linux网络编程,Linux编程杂项,Linux窗口编程,Linux多线程编程,Linux脚本编程

    Unix环境高级编程——线程控制PPT

    《Unix环境高级编程》第十二章——线程控制PPT

    多线程编程UNIXLinux下的多线程编程.pdf

    多线程编程UNIXLinux下的多线程编程.pdf

    Unix-Linux-Windows-OpenMP多线程编程.pdf

    。。。

    Unix-Linux-Windows-OpenMP多线程编程.docx

    。。。

    UNIX系统编程 part2

    UNIX系统编程 PDF part2 不错的一本UNIX 系统编程书籍

    UNIX系统编程.pdf

    本书是UNIX系统编程的经典教材,并基于最新的UNIX标准进行了更新,其内容完全覆盖文件、信号、POSIX线程、UDP、Web和客户机-服务器等相关内容,并对通信、并发和多线程问题进行了透彻的研究,对复杂的概念进行了...

    UNIX 多线程多进程编程

    主要根据本人在UNIX系统上的编程实践经验总结而成, 既做为自己在 一个时期内编程实践的部分总结, 又可成为文章发表. 对UNIX程序员初学者来 说是一个小小的经验, 仅供参考; 对UNIX老手来说则不值一提。 。 6.wait...

    多线程编程指南--linux多线程编程的好东东

    该《多线程编程指南》基于POSIX 标准IEEE Std 1003.1 1996 版(又称作ISO/IEC 9945–1 第二版)。最新修订版的POSIX 标准IEEE Std 1003.1:2001(又称作ISO/IEC 9945:2002 和单一UNIX 规范版本3)中也提供了这些功能...

    unix环境下的线程库实现

    unix环境下的线程库实现,包含若干个重要函数,是大学学习unix环境高级编程必备的题目。

    多线程编程原理与实战(超优秀)

    包含详细介绍多线程编程的四个文档及可运行的代码: 1、多线程编程-API.doc 2、多线程编程-互斥锁.doc 3、多线程编程-信号量.doc 4、多线程编程-监控线程.doc 其中监控线程部分有较好的参考价值。

    unix高级环境编程-第三版-图书-源代码

    本书是被誉为UNIX编程“圣经”的Advanced Programming in the UNIX Environment一书的更新版。在本书第1版出版后的十几年中,UNIX行业已经有了巨大的变化,特别是影响UNIX编程接口的有关标准变化很大。本书在保持了...

    Unix System Programming (Unix系统编程)

    本书是UNIX系统编程的经典教材,是基于最新UNIX标准的参考书,对UNIX编程本质进行了清晰透乇的介绍。本书完全覆盖文件、信号、信号量、 POSIX线程以及客户端一服务器通信等内容,对通信、并发和多线程问题进行了深入...

    LINUX.UNIX系统编程手册(下册)

    《linux/unix系统编程手册(上、下册)》是介绍linux与unix编程接口的权威著作。linux编程资深专家michael kerrisk在书中详细描述了linux/unix系统编程所涉及的系统调用和库函数,并辅之以全面而清晰的代码示例。...

    学习笔记多线程Unix编程

    学习笔记多线程Unix编程

    UNIX系统编程 中文版 pdf

    本书是UNIX系统编程的经典教材,是基于最新UNIX标准的参考书,对UNIX编程本质进行了清晰透乇的介绍。本书完全覆盖文件、信号、信号量、 POSIX线程以及客户端一服务器通信等内容,对通信、并发和多线程问题进行了深入...

    unix多线程/多进程编程

    unix多线程和多进程同步技术概要,笼罩了常见的unix多线程和多进程函数,还有详细文字介绍。

    UNIX环境高级编程-中文第三版

    本书是被誉为UNIX编程“圣经”的Advanced Programming in the UNIX Environment一书的更新版。书中除了介绍UNIX文件和目录、标准I/O库、系统数据文件和信息、进程环境、进程控制、进程关系、信号、线程、线程控制、...

    UNIX多线程编程指南

    详细讲解了linux/unix的多线程的原理,编程方法,线程结构等等,一步一步教你进行多线程的编程。

    Linux多线程 C语言编程关于多线程

    统中才引入多线程机制,如今,由于自身的许多优点,多线程编程已经得到了广泛的应用。 本文我们将介绍在Linux 下编写多进程和多线程程序的一些初步知识。 1 引言 对于没有接触过 Unix/Linux 操作系统的人来说,fork ...

Global site tag (gtag.js) - Google Analytics