线程的创建

来源:互联网 发布:淘宝上卖的龙钞真假 编辑:程序博客网 时间:2024/06/13 13:45

1.什么是线程:

                  线程是进程内部的一条执行序列(执行流),每个进程至少有一条执行序列:main的执行体。进程可以通过线程库创建 N 条线程,这些新创建的线程称之为函数线程,main 函数所代表的线程为主线程

2.线程与进程区别:

            1)进程是资源分配的最小单位,线程是 CPU 调度的最小单位
            2)线程是轻量级的进程
           3)管理方式不同,进程是 PCB 管理,线程是由线程结构管理

3.线程实现的三种方式:

           1)用户级(n:1)

用户级实现

有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在. 应用程序可以通过使用线程库设计成多线程程序. 通常,应用程序从单线程起始,在该线程中开始运行,在其运行的任何时刻,可以通过调用线程库中的派生例程创建一个在相同进程中运行的新线程。

用户级线程仅存在于用户空间中,此类线程的创建、撤销、线程之间的同步与通信功能,都无须利用系统调用来实现。用户进程利用线程库来控制用户线程。由于线程在进程内切换的规则远比进程调度和切换的规则简单,不需要用户态/核心态切换,所以切换速度快。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少为了在操作系统中加入线程支持,采用了在用户空间增加运行库来实现线程,这些运行库被称为“线程包”,用户线程是不能被操作系统所感知的。用户线程多见于一些历史悠久的操作系统,例如Unix操作系统

用户级线程驻留在用户空间或模式。运行时库管理这些线程,它也位于用户空间。它们对于操作系统是不可见的,因此无法被调度到处理器内核。每个线程并不具有自身的线程上下文。因此,就线程的同时执行而言,任意给定时刻每个进程只能够有一个线程在运行,而且只有一个处理器内核会被分配给该进程。对于一个进程,可能有成千上万个用户级线程,但是它们对系统资源没有影响。运行时库调度并分派这些线程。

用户级特点内核对线程包一无所知。从内核角度考虑,就是按正常的方式管理,即单线程进程(存在运行时系统)用户级优点

可以在不支持线程的操作系统中实现。

创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多, 因为保存线程状态的过程和调用程序都只是本地过程

允许每个进程定制自己的调度算法,线程管理比较灵活。这就是必须自己写管理程序,与内核线程的区别

线程能够利用的表空间和堆栈空间比内核级线程多

不需要陷阱,不需要上下文切换,也不需要对内存高速缓存进行刷新,使得线程调用非常快捷

线程的调度不需要内核直接参与制简单。用户级缺点

线程发生I/O或页面故障引起的阻塞时,如果调用阻塞系统调用则内核由于不知道有多线程的存在,而会阻塞整个进程从而阻塞所有线程, 因此同一进程中只能同时有一个线程在运行

页面失效也会产生类似的问题。

一个单独的进程内部,没有时钟中断,所以不可能用轮转调度的方式调度线程

资源调度按照进程进行,多个处理机下,同一个进程中的线程只能在同一个处理机下分时复用


    2)内核级(n:n)

内核级实现

内核线程建立和销毁都是由操作系统负责、通过系统调用完成的。在内核的支持下运行,无论是用户进程的线程,或者是系统进程的线程,他们的创建、撤销、切换都是依靠内核实现的。

线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口. 内核为进程及其内部的每个线程维护上下文信息,调度也是在内核基于线程架构的基础上完成。

内核线程驻留在内核空间,它们是内核对象。有了内核线程,每个用户线程被映射或绑定到一个内核线程。用户线程在其生命期内都会绑定到该内核线程。一旦用户线程终止,两个线程都将离开系统。这被称作”一对一”线程映射,

线程的创建、撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程

这些线程可以在全系统内进行资源的竞争

内核空间内为每一个内核支持线程设置了一个线程控制块(TCB),内核根据该控制块,感知线程的存在,并进行控制

每个用户线程都直接与一个内核线程相关联.

内核级特点当某个线程希望创建一个新线程或撤销一个已有线程时,它进行一个系统调用内核级优点

多处理器系统中,内核能够并行执行同一进程内的多个线程

如果进程中的一个线程被阻塞,能够切换同一进程内的其他线程继续执行(用户级线程的一个缺点)

所有能够阻塞线程的调用都以系统调用的形式实现,代价可观

当一个线程阻塞时,内核根据选择可以运行另一个进程的线程,而用户空间实现的线程中,运行时系统始终运行自己进程中的线程

信号是发给进程而不是线程的,当一个信号到达时,应该由哪一个线程处理它?线程可以“注册”它们感兴趣的信号

3)混合模式(n:m)

  在一些系统中,使用组合方式的多线程实现, 线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行. 一个应用程序中的多个用户级线程被映射到一些(小于或等于用户级线程的数目)内核级线程上。

4.内核级和用户级的区别:

内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的。

用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。

用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。

在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。

用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。

5.线程的创建和结束:

(线程库文件的使用)pthread

1)创建一个函数线程!!:int pthread_create(pthread_t *id, pthread_attr_t *attr,void* (*fun)(void*), void *arg);

2)包含线程创建函数的源代码要想生成可执行文件,必须::gcc -o pthread pthread.c -lpthread

3)创建出来的函数线程不同于函数调用,函数调用是这条执行流中的一部分。函数线程是创建出一条独立的执行序列,他与主线程同时执行。

4)线程结束: int pthread_exit(void *); 参数可以设置线程结束状态
    等待线程结束: int pthread_join(pthread_t id, void **);
    可以获取到等待的线程通过 pthread_exit 设置的结束状态信息

6.线程函数传参:
   1)将值强转成 void*int a = (int) arg;
   2)将地址强转成 void*int a = *(int*)arg;



原创粉丝点击