线程基础

       1、什么是线程?
        线程是进程内部的一条执行序列,或者执行流,每一个进程至少有一条线程,称之为主线程,从代码角度看,就是main函数的函数体,在主线程中可以通过线程库创建其他线程(函数线程),主线程和函数线程会同时向下运行。线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。由于每个线程占用的CPU时间是由系统分配的,因此可以把线程看成操作系统分配CPU时间的基本单位。对于单CPU单核的情况下,从用户角度看来,多个线程是同时执行的,但从操作系统调度上看,各个线程是交替执行的,系统不停地在各个线程之间切换,每个线程只有在系统分配给它的时间片内才能取得CPU的控制权,执行线程中的代码。
        2、为什么在多进程的情况下又引入多线程呢?
        这是因为多线程相对于多进程有以下优点:
    (1)在多进程情况下, 每个进程都有自己独立的地址空间,而在多线程情况下,同一进程内的线程共享进程的地址空间,因此创建一个新的进程时就要耗费时间来为其分配系统资源,而创建一个新的线程花费的时间则要少得多。
    (2)在系统调度方面, 由于进程地址空间独立而线程共享地址空间,线程间的切换速度要远远快过进程间的切换速度。
    (3)在通信机制方面, 进程间的数据空间相互独立,彼此通信要以专有通信方式进行,通信时必须经过操作系统,而同一进程内的多个线程共享数据空间,一个线程的数据可以直接提供给其他线程使用,而不必经过操作系统,因此线程间的通信更加方便和省时。
   
(4)可以提高应用程序的响应速度。 在图像界面程序中,如果有一个非常耗时的操作,它会导致其他操作不能进行而等待个操作,此时界面响应用户操作的速度会变得很慢。多线程环境下可以将这个非常耗时的操作由一个单独的线程来完成,这个线程在用完操作系统分配给它的时间片后,就会让出CPU,这样其他操作便有机会执行了。
    (5)可以提高多处理器效率,现在许多计算机都是采用多核技术,在这种情况下,可以让多个线程在不同的处理器上同时运行,从而大大提高程序执行速度。因此多线程更能发挥硬件的潜力。
     (6)可以改善程序的结构,对于要处理多个命令的应用程序,可以将对每个命令的处理设计成一个线程,从而避免设计成大程序时造成的程序结构复杂。
        线程以上的优点可以用两个字概括,就是“节约”:节约资源,节约时间。既然线程有这么多优点,那能不能不要进程了?答案肯定是不能的,因为线程是进程内部的一条执行序列,同一进程内的多个线程共享共享全局数据、堆区数据,包括打开的文件描述符,进程为它们的共享提供了支持,线程必须依赖进程而存在,所以不能没有进程。
       3、线程的使用
    (1)线程的创建

#include <pthread.h>
int pthread_create(pthread_t *id,pthread_attr_t *attr,void *(pthread_fun)(void *),void *arg);
返回值:若创建成功返回0,若不为0说明创建失败。

id:该参数是一个指针,当线程创建成功时用来返回创建的线程id。
attr:该参数用于指定线程的属性,默认属性为NULL。
pthread_fun:该参数为一个函数指针,指向线程创建后要调用的函数,这个被线程调用的函数称为线程函数。
arg:该参数指向传递给线程函数的参数。
         创建时给线程函数传参的两种方式:
        1. 值传递:最多传递4字节的数据,将传递的值字节强转为void *类型的指针,arg的类型是void *,记录的是传递的值。
        2. 地址传递:将要传递的值的地址转化为void *类型的指针,arg的类型是void *,记录的是传递的值的地址。
    (2)线程终止
        Linux下有两种方式可以使线程终止,一种是通过return从线程函数返回, 另一种是通过调用函数pthread_exit()使线程退出。

#include <pthread.h>
void pthread_exit(void *retval);

         如果主线程调用pthread_exit 函数,则仅仅是主线程消亡,进程不会结束,进程内的其他线程也不会终止,直到所有线程结束,进程才会结束。在主线程中,如果从main函数返回或是调用了exit函数退出主线程,则整个进程将终止,此时进程中所有线程也将终止,因此在主线程中不能过早地从main的数返回。
(3)等待线程结束

#include <pthread.h>
int pthread_join(pthread_t id,void **retval);

        pthread_join()的调用者将被挂起并等待id线程终止,pthread_join()函数中的retval指向pthread_exit函数中的retval,pthread_ join()函数仅允许一个线程使用pthread_join()函数等待它的终止。
(4)取消一个线程

#include <pthread.h>
int pthread_cancel(pthread_t id);

         该函数只是发出取消请求,并不会阻塞。
        4、线程的实现方式
    (1)用户级线程

        线程的创建、销毁、管理都是在用户空间完成的,内核只会将其识别为一个进程,一个线程。优点是内核代码简单,线程切换速度快,线程切换在用户空间完成,不需要陷入内核。缺点是用户代码复杂,用户必须自己管理线程,包括线程调度,如果一个线程阻塞,整个进程都将会阻塞。
    (2)内核级线程
        
  线程的创建、销毁、管理由操作系统内核完成。优点是用户代码简单,如果一个线程阻塞,会切换到其他线程。缺点是内核代码复杂,切换速度慢,每次切换需要陷入内核。
    (3)混合级线程
        
线程的创建、销毁、管理一部分是在用户空间完成的,一部分在内核完成。它的优点结合了用户级线程和内核级线程的优缺点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值