欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-07 17:46:01
...
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,否则失败
 
 
相关标签: thread unix linux