`
brxonline
  • 浏览: 65024 次
  • 性别: 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);
}

 

分享到:
评论

相关推荐

    UNIX编程艺术 - 扫描版 - 书签

    根据提供的信息,我们可以了解到这是一本关于《UNIX编程艺术》的经典书籍,该书提供了高清扫描版本,并且包含完整的书签,方便读者进行阅读与查阅。接下来,我们将从这本书的主题出发,探讨几个重要的UNIX编程概念与...

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

    Unix-Linux-Windows-OpenMP 多线程编程知识点总结 POSIX 的基本知识 POSIX(Portable Operating System Interface)是一种可移植操作系统接口标准,旨在提供源代码级的软件可移植性。POSIX 标准定义了操作系统应该...

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

    Unix-Linux-Windows-OpenMP 多线程编程 本文档主要介绍 Unix/Linux 多线程编程接口及编程技术,重点讲解 POSIX 的一些基本知识。POSIX 是可移植操作系统接口(Portable Operating System Interface)的首字母缩写,...

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

    本资料集专注于"Linux编程技术-多线程-网络编程",它涵盖了UNIX环境高级编程、Linux网络编程、Linux多线程编程、Linux窗口编程以及Linux脚本编程等多个核心主题。这些内容都是构建高效、可靠且可扩展的Linux应用的...

    Linux系统编程-线程

    在类Unix系统中,早期并没有线程的概念,大约是在80年代才引入了这个概念。因此,线程在这些系统中通常是通过进程机制来实现的。 1. **轻量级进程**(LWP):具有自己的PCB,创建线程时使用的底层函数与创建进程时...

    UNIX高级编程5-6(大师著作)

    通过学习《UNIX高级编程》,程序员不仅可以掌握UNIX编程的核心技术,还能培养出系统级别的思维,从而能够设计和编写更高效、更稳定、更健壮的软件系统。无论是对初学者还是经验丰富的开发者,这都是一本极具价值的...

    unix网络编程--第一卷----套接口API

    《UNIX网络编程——第一卷——套接口API》是网络编程领域的经典之作,尤其在UNIX操作系统环境下,这本书被视为不可或缺的学习资源。作者深入浅出地讲解了网络通信的基础理论和实际操作,帮助开发者理解如何利用套...

    UNIX----系统编程

    - **POSIX标准**:提供了跨平台的UNIX编程接口,如pthread库用于线程编程。 通过深入学习和实践以上知识点,你将能够熟练地进行UNIX系统编程,开发出高效、稳定的应用程序。记得结合《UNIX系统编程》这样的参考...

    UNIX环境高级编程-pdf

    《UNIX环境高级编程》是一本深受程序员和系统管理员喜爱的经典之作,主要针对那些希望深入理解UNIX操作系统,并能熟练进行...无论是自学还是作为参考手册,这本书及其相关资料都能为你的UNIX编程之路提供强大的支持。

    UNIX网络编程-第2卷-进程间通讯

    《UNIX网络编程-第2卷-进程间通讯》是一本深入探讨UNIX系统中进程间通信(Inter-Process Communication, IPC)的经典著作。该书详细阐述了如何在多进程环境中实现有效的数据交换,这对于理解操作系统原理、开发高效...

    Unix编程艺术/Unix环境高级编程(第二版)/Unix网络编程(第二版)

    《Unix编程艺术》、《Unix环境高级编程(第二版)》和《Unix网络编程(第二版)》是三本在IT领域中具有深远影响力的经典著作,涵盖了Unix操作系统的核心概念、系统调用、进程管理、文件操作、网络通信等多个重要主题...

    UNIX高级编程18-20(大师著作)

    UNIX系统以其稳定、高效和强大的命令行接口而著名,对于系统管理员和高级程序员来说,深入理解和掌握UNIX的高级编程技巧至关重要。"UNIX高级编程18-20(大师著作)"这部分内容可能涵盖了以下几个关键知识点: 1. **...

    Linux/UNIX网络编程》-甘刚-电子教案

    《Linux/UNIX网络编程》是甘刚教授撰写的一本深入探讨网络编程技术的专业书籍,主要针对使用Linux和UNIX操作系统进行网络应用开发的程序员。这本书详细介绍了如何在这些系统上构建网络应用程序,涵盖了从基础概念到...

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

    在Unix环境中,线程控制是高级编程中的一个重要概念,它涉及到多线程程序的设计和管理。线程控制允许程序员在单个进程中同时执行多个独立的执行流,从而提高程序的并发性和效率。以下是对《Unix环境高级编程》第十二...

    QNX-UNIX-POSIX-C函数手册-chm格式.7z

    《QNX-UNIX-POSIX-C函数手册》是一份针对编程初学者的宝贵资源,尤其适合那些在Linux环境中使用C语言进行开发的程序员。这份手册详细介绍了C语言标准库以及与QNX、UNIX和POSIX操作系统相关的扩展函数,旨在帮助...

    HP-UNIX.rar_hp_hp unix_hp-unix download

    1. **多线程和多进程支持**:HP-UNIX支持多线程和多进程并发执行,使得系统能够高效地处理多个任务,提升整体工作效率。 2. **高级内存管理**:具备先进的内存分配和回收机制,确保系统的稳定运行,减少因内存泄露...

    Unix编程艺术中文版(非加密,带目录)

    根据提供的标题“Unix编程艺术中文版(非加密,带目录)”及描述“Unix编程艺术中文版”,可以推测这是一本介绍Unix系统编程原理、技巧和最佳实践的书籍。本书可能涵盖Unix系统的背景知识、核心概念、编程工具和技术...

    UNIX环境高级编程--原始代码

    10. **POSIX线程(pthread)编程**:介绍多线程的概念,线程创建(pthread_create())、同步(pthread_mutex_t, pthread_cond_t等)和线程属性设置。 通过实践这些示例代码,开发者不仅可以了解UNIX系统的底层工作...

    UNIX高级编程21-23(大师著作)

    "UNIX高级编程21-23(大师著作)"这个压缩包文件包含了三部分关于这一主题的深度学习资料,分别命名为022.PDF、021.PDF、023.PDF,这些PDF文件很可能是从一本经典的UNIX编程书籍中提取的章节。 UNIX高级编程涵盖了...

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

    ### 多线程编程在UNIX/Linux环境中的应用与优势 多线程编程作为一种高效的数据处理方式,在UNIX/Linux环境下得到了广泛的应用。与传统的单线程进程相比,多线程编程能够显著提升程序的性能和响应速度,尤其是在现代...

Global site tag (gtag.js) - Google Analytics