多线程(一):进程、线程与核心对象介绍

操作系统核心对象:

  内核对象是由内核拥有的,而不是由进程拥有。

  如果你的进程创建了一个内核对象的句柄,然后你的进程中止运行,那么,内核对象不一定会被销毁。

  内核对象的存在时间可以比创建该内核对象的进程长很多。 内核需要知道多少个进程正在使用某个内核对象,所以内核对象有一个使用计数。使用计数是内核对象常用的数据成员

  CreateThread的返回值handle是一个核心对象(Kernel Objects)。Handle是一个指针,指向操作系统内存空间的一个对象,此对象不允许直接取得,为的是维护系统的完整性与安全性。

   Win32系统中包括如下核心对象: (1)进程(processes)、(2)线程(threads)、(3)文件(files)、(4)事件(events)、(5)信号量(semaphores)、(6)互斥器(mutexes)、(7)管道(Pipes) 核心对象保持了一个引用计数,一旦引用计数降至0,核心对象便自动消毁。

  

句柄:

  当调用一个创建内核对象的函数时,该函数返回一个句柄,用来标志这个内核对象。

  这个句柄值是和进程密切相关的,只能在这个进程中使用,如果在其他的进程中使用这个句柄值操作句柄,会失败。

   在这个进程中的其他线程,可以使用这个句柄值

   当一个进程初始化的时候,系统为他分配一个句柄表。内核对象的句柄实际上是在句柄表中的一个索引值。

 

Event对象:
  Win32中最具弹性的同步机制就是Event对象了。Event对象是一种核心对象,它的唯一目的就是成为激发状态或未激发状态,这两种状态完全由程序来控制,不会成为Wait…的副作用。
  为了产生一个Event对象,必须调用CreateEvent();

 

进程:

  进程通常被定义为一个正在运行的程序的实例,进程是不活泼,进程只是线程的容器,一个进程可以包括多个线程,从不执行任何东西。

 

线程:

  线程总是在某个进程环境中创建的,线程在它的进程地址空间中执行代码,并且在进程的地址空间中对数据进行操作。

 

线程状态:

  新建状态:没有调用start方法之前

  运行(running)态(执行run方法):占有处理器正在运行 

  就绪(ready)态(调用start方法之后,等待cup分配执行权):指具备运行条件,等待系统分配处理器以便运行 

  等待(wait)态(waitsleep、锁资源被其他线程抢占等):又称为阻塞(blocked)态或睡眠(sleep)态,指不具备运行条件,正在等待某个事件的完成 

  运行态—→等待态:等待使用资源;如等待外设传输;等待人工干预
  等待态—→就绪态:资源得到满足;如外设传输结束;人工干预完成
  就绪态—→运行态:CPU空闲时选择一个就绪线程。
  运行态—→就绪态:运行时间片到;出现有更高优先权线程。

 

使用多线程比使用多进程的好处:

  1、线程廉价

  2、启动比较快,退出比较快

  3、对系统资源的冲击比较小

  4、线程彼此分享了大部分核心对象的拥有权

 

多线程程序的风险:

  1、多线程程序无法预期,即每次执行结果不同

  2、 执行次序无法保证,即线程间的执行顺序随机

  3、线程并不总是立刻启动

 

注意事项:

  各线程的数据要分离开来,避免使用全局变量 确定知道线程的状态,不要径自结束程序而不等待它们的结束。

线程状态切换(也称为线程上下文切换):
  硬件计时器发现执行时间过长,就会发出一个中断,操作系统会从CPU中取出该线程的当前状态(数据寄存器内容)保存到堆栈中,再拷贝到一个CONTEXT结构,以备后用

  多线程状态切换导致代码执行结果的随机性

  单CUP的机器上,多线程不能提高程序的性能,但能提高cup效率

 

线程种类:

  用户线程(非守护线程):新创建的线程,当主线程挂掉时,不受影响

  守护线程:当所有用户线程和主线程都停止,守护线程自动停止。在start之前调用setDeamon(true)方法设置为守护线程。

  主线程:main函数所在线程

  子线程:主线程中创建的线程

 

保证线程安全的方式:

  线程锁、临界区(critical sections)、分模块使线程之间尽量不共用代码

 

线程间通讯方式:

  event(核心对象:事件)、静态变量(比如事件队列)、条件变量、互斥锁、wait方法等

 

线程间通信的两个基本问题:同步与互斥

线程同步

   线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒

线程互斥

   各线程排它访问共享的操作系统资源。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源 线程互斥是一种特殊的线程同步

 

Mutex和critical section区别:
  锁住一个未被拥有的mutex比锁住一个未被拥有的critical section,需要花费几乎100倍的时间。因为critical section不需要进入操作系统核心。
  Mutex可以跨进程使用,critical section则只能在下个线程中使用。
  等待一个Mutex时,可以指定“结束等待”的时间长度,但对于critical section则不行。

 

解决死锁 ---- 打破四个条件:
  通过强行规定任务获得资源的方式防止死锁:几个任务要访问资源A,B和C,任务以同样的次序获得和释放资源
  任务一次性请求所需要的资源,或要求被拒绝使用某一资源的任务,立即释放它所持有的所有其它资源,然后重新获得。

线程中止的几种方法:线程的退出应该尽可能的使用第一种方式,让线程自己正常的退出
  线程的入口函数返回
  在线程内调用ExitThread,线程自行销毁
  在同一个进程的其他线程中调用TerminateThread函数,终了指定线程。
  包含线程的进程中止运行

posted @ 2020-08-25 23:39  吉尔加斯  阅读(526)  评论(0编辑  收藏  举报