Unix环境高级编程笔记:11、线程

1、线程概念
    线程包含了表示进程内执行环境必须的信息,其中包括进程中标识线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。
 
 

 
 
2、线程标识
    线程ID用pthread_t数据类型表示
    
必须使用函数对二个线程ID进行比较
       #include <pthread.h>
       int pthread_equal(pthread_t t1, pthread_t t2);
 
通过pthread_self获得自身线程ID
#include <pthread.h>
pthread_t pthread_self(void);
 
 

 
 
3、创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

当pthread_create成功返回时,由tidp指各的内存单元被设置为新创建线程的线程ID

attr参数用于定制各种不同的线程属性。
 
pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()创建线程,以及调用 pthread_atfork()函数建立fork处理程序时,需要链接该库。
在编译中要加 -lpthread参数
gcc thread.c -o thread -lpthread

create_thread.c
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.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(int argc, char **argv) {
int err;
err = pthread_create(&ntid,NULL,thr_fn,NULL);
if(err != 0) {
printf("pthread create error");
}
printids("main thread:");
sleep(1);
exit(0);
}
 
 
 
 

 
4、线程终止
    如果进程中的任一线程调用了exit、_Exit或者_exit,那么整个进程就会终止。
    如果信号的默认动作是终止进程,那么把信号发送到线程会终止整个进程。
 
    线程退出方式
    1)线程只是从启动例程中返回,返回值是线程的退出码
    2)线程可以被同一进程中的其他线程取消。
    3)线程调用pthread_exit
    
       #include <pthread.h>
       void pthread_exit(void *retval);
 
retval是一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join访问到这个指针。
   #include <pthread.h>
   int pthread_join(pthread_t thread, void **retval);
调用线程将一直被阻塞,直到指定的线程调用pthread_exit,从启动例程中返回或者被取消。
 
获取已终止的线程的退出码
thread_exit_code.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
 
void *thr_fn1(void *arg) {
printf("thread 1 returning\n");
return ((void*)1);
}
 
void *thr_fn2(void *arg) {
printf("thread 2 returning\n");
return ((void*)2);
}
 
int main(int argc, char **argv) {
int err;
pthread_t tid1,tid2;
void *tret;
 
err = pthread_create(&tid1,NULL,thr_fn1,NULL);
if(err != 0) {
printf("can`t create thread1 %s",strerror(err));
exit(0);
}
err = pthread_create(&tid2,NULL,thr_fn2,NULL);
if(err != 0) {
printf("can`t create thread1 %s",strerror(err));
exit(0);
}
 
 
err = pthread_join(tid1,&tret);
if(err != 0) {
printf("can`t join with thread 1 %s",strerror(err));
exit(0);
}
printf("thread 1 exit code %s\n",strerror(err));
 
 
err = pthread_join(tid2,&tret);
if(err != 0) {
printf("can`t join with thread 2 %s\n",strerror(err));
exit(0);
}
printf("thread 2 exit code %s\n",strerror(err));
exit(0);
}
 
 
 
 
线程可以通过调用pthread_cancel函数来请求取消同一进程中的其他线程。
       #include <pthread.h>
 
       int pthread_cancel(pthread_t thread);
 
 
 

 
5、线程同步
    互斥变量用pthread_mutex_t数据类型表示,在使用互斥变量以前,必须首先对它进行初始化。
    可以把它设置为常量PTHREAD_MUTEX_INITALIZER(只对静态分配的互斥量)
    通过调用pthread_mutex_init函数进行初始化。
    如果动态的分配互斥量(malloc),那么释放内存前需要调用pthread_mutex_destroy
       #include <pthread.h>
 
       int pthread_mutex_destroy(pthread_mutex_t *mutex);
       int pthread_mutex_init(pthread_mutex_t *restrict mutex,
              const pthread_mutexattr_t *restrict attr);
        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
 
对互斥量进行加锁,需要调用pthread_mutex_lock,如果互斥量已经上锁,调用线程将阻塞直到互斥量被解锁。对互斥量解锁,需要调用
pthread_mutex_unlock
       #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);
如果不希望被阻塞,它可以使用pthread_mutex_trylock尝试对互斥量进行加锁。
如果调用pthread_mutex_trylock时互斥量处于未锁住状态,那么将锁住互斥量,不会出现阻塞并返回0,否则失败
 
 

猜你喜欢

转载自hackxin.iteye.com/blog/1975086