linux多线程

来源:互联网 发布:淘宝商品广告违规 编辑:程序博客网 时间:2024/06/05 23:45

线程,有时候被称为轻量级进程(light weight Process,LWP)是程序执行的最小单元。每个程序至少有一个线程,若程序只有一个线程,那就是程序本身。

一个进程在同一时间只能做一件事,有了多线程后一个进程同一时间可以做多件事情。(这里是从并发的角度考虑的,对于单核CPU,某一时刻只会有一个线程再执行),一个线程阻塞了并不会影响另一个线程,多线程的进程尽可能的利用系统CPU资源。对于一个进程来说也不是线程越多越好,当线程超过一定数量时候效率会变低。

线程包含了表示进程内执行环境必须的信息,包括线程的线程ID,一组寄存器值,栈,调度优先级和策略,信号屏蔽字,error变量以及线程的私有数据。进程内部所有的信息对于线程是共享的,包括执行代码全局变量,和堆内存,栈以及文件描述符。


线程标识:

就像每个进程都有个进程ID一样,线程也有自己的ID。

进程ID用pid_t来表示,它是一个unsigned int。

线程ID用批pthread_t表示,在ubuntu 系统:

/usr/include/i386-linux-gnu/bits/pthreadtypes.h

pthread_t的定义为:

typedef unsigned long int pthread_t

线程可以通过pthread_self()函数获取自身的线程ID。

创建线程:

在进程中只有一个控制线程。

程序开始运行的时候每个进程只有一个线程,它是以单线程的方式启动的,在创建多个进程以前,进程的行为与传统的进程没有区别。

创建线程的函数是pthread_create()。所需头文件为pthread.h其定义如下:

Int pthread_create(pthread_t *thread,constpthread_attr_t * attr,void *(*start_routine)(void *),void *arg);

线程一旦创建好,内核就可以调度内核线程来执行start_routine 函数指针所指向的函数。

线程的退出,主线程一旦退出,其它线程也会被退出,

第二个参数如果传入为NULL,则为线程使用系统默认属性,当然也可以通过定义线程变量:

pthread_attr_t  attr_t;设置相关创建线程的属性,比如可分离性。

最后一个参数为start_routine 函数指针所指向的函数的参数。

pthread_join(pthread_t th,void **thr_return)

pthread_join 函数用于挂起当前线程,直至th指定的线程终止为止。(如果不这样的话,主线程退出后,子线程则也直接被清除内存)

如果另一个线程返回值不是NULL则保存在thr_return地址中。

pthread_detach(pthread_t thread);设置线程成为可分离状态,使用pthread_create创建的线程默认是不可分离状态。

可分离线程的使用场景:

主线程不需要等待子线程退出

主线程不关心子线程的返回码

pthread_cancel(pthread_t thread);
函数允许一个线程取消thread指定的另一个线程。

int pthread_equal (pthread_t  th1,pthread_t th2)

pthread_equal 函数比较th1与th2 是否为同一线程。

线程的同步技术

线程共享进程的内存空间,打开的文件描述符,全局变量。

当有多个线程同时访问一块内存空间或者一个变量一个文件描述符,如果不加控制,那么可能会出现意想不到的结果。互斥是相互排斥的意思它是一种锁,互斥用于保护多个线程共享数据和结构不会被同时修改。

一个互斥锁只有两个状态locked –加锁unlocked --- 解锁

任何时刻只能有一个线程来掌握某个互斥上锁。一个线程如果试图在一个已经加锁的互斥上再加锁,这个线程会被挂起,直到加锁的线程释放掉互斥锁为止。

一个简单线程使用例子:

#include <stdio.h>#include <stdlib.h>#include<unistd.h>#include<sys/types.h>#include <string.h>#include <sys/wait.h>#include<pthread.h>#include <errno.h>struct student{char name[20];int age;};void *func(void *par) {printf("thread start! \n");int *thread_rv = (int *) malloc(sizeof(int));*thread_rv = 100;struct student *tmp = (struct student *) par;printf("name:%s \n", tmp->name);printf("age:%d \n", tmp->age);return thread_rv;}int main(void){int i = 0;pthread_t thrd;int *thread_rv;struct student p_t;strcpy(p_t.name, "hsc"); p_t.age = 20;if (pthread_create(&thrd, NULL, func, &p_t) != 0) //创建线程并传入参数struct student p_t;{printf("%d %s \n", i, strerror(errno));return -1;}pthread_join(thrd, (void **) &thread_rv); //主线程挂起,等待thrd退出printf("thread return value:%d \n", *thread_rv); //输出线程返回值return 0;}


 




0 0