文档库 最新最全的文档下载
当前位置:文档库 › 线程笔记

线程笔记

线程笔记
线程笔记

多线程

一、概述

进程:是一个正在执行的程序

每一个进程都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。线程:就是进程中的一个独立控制单元,线程控制着进程的执行。

一个进程至少有一个线程

Java VM 启动的时候会有一个进程java.exe

该进程中至少一个线程负责java程序的执行。

而且这个线程运行的代码存在于main方法中,该线程称为主线程。

扩展:其实更细节说明jvm,jvm启动不止一个线程,还有负责垃圾回收的线程。

二、线程创建方式。

Thread类对线程这类事物描述的类

1、继承Thread

步骤:

1)定义类继承Thread。

2)复写Thread类的run方法

3)调用线程的start方法,作用:启动线程,调用run方法

2、实现Runnable接口

步骤:

1)定义类实现Runnable接口

2)覆盖Runnable接口中的run方法

3)将Runnable接口的子类对象传递给Thread的构造函数,目的是让线程去指定对象的run

方法,就必须明确该run方法的对象

4)调用Thread类的start方法开启线程并调用Runnable接口子类的run方法

3、实现方式与继承方式有什么区别

实现方式好处:避免了单继承的局限性

在定义线程时,建议使用实现方式

两种方式区别:

继承Thread:线程代码存放在Thread子类的run方法中。

实现Runnable,线程代码存在接口的子类的run方法。

4、Thread 类thread.start()方法与thread.run()的区别

thread.start():启动线程,调用run方法。

thread.run():仅仅是调用run方法。

5、线程生命周期

6、获取和设置线程名称

static Thread currentTrread():获取当前线程对象

getName():获取线程名称

setName():设置线程名称

7、多线程

多个线程抢占cpu资源运行。随机性

多线程的运行出现了安全问题:(try{Thread.sleep()}catch(){});

问题的原因:

当多条语句在操作同一个线程共享的数据时,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。

解决办法:

对多条操作共享的语句,智能让一个线程都执行完。在执行过程中,其他线程不能参与执行。

Java对于多线程的安全问题提供了专业的解决方式,就是同步代码块

synchronized(对象)

{

需要被同步的代码

}

对象如同锁。持有锁的线程可以在同步中执行。

没有持有所得线程即使获取cpu的执行权,也进不去,因为没有获取锁。

例子.火车上的卫生间。

同步的前提:

1,必须要有两个或两个以上的线程。

2,必须是多个线程使用同一个锁。

必须保证同步中只能有一个线程在运行。

好处:解决了多线程的安全问题。

弊端:多个线程需要判断所,较为消耗资源

练习2:

需求银行有一个金库,有两个储户分别存300,每次存100,存3次。

目的:该程序是否有安全问题,如果有,如何解决?

如何找问题:

1,明确哪些代码是多线程运行代码。

2,明确共享数据。

3,明确多线程运行代码中哪些语句是操作共享数据的

同步函数。

在所需要同步的方法用synchronized修饰

如:public synchronized add(){}

同步函数使用的是哪一个锁?

同步函数需要被对象调用,那么函数都会有一个所属对象的引用,就是this

所以同步函数的锁就是this,不能将Thread类的run方法修饰为同步方法,如run方法为同步方法,则只有一个线程对象持有锁,直到run方法结束为止。

可以通过该程序进行验证。

使用两个线程来买票。

一个线程在同步代码块中。一个线程在同步函数中。都在执行买票动作。

如果同步函数被静态修饰后,使用的锁是什么?

锁不是this,因为静态方法也不可以定义this。静态方法进内存的时候没有本类对象,但是一定有该类对应的字节码文件对象。

类名.class 该对象的类型是Class

静态的同步方法,使用的锁是该方法所在类的字节码文件对象,类名.class

8、单例设计模式

饿汉式

Class Single

{

private static final Single s=new Singel();

private Single(){}

pulbic static Single getInstance()

{

return s;

}

}

懒汉式

class Single

{

private static Single=null;

private Single(){}

pulbic static synchronized Single getInstance()// →a ->b 线程{

if(s==null)

S=new Single();

return s;

}

}

以上多次判断锁,较耗资源,修改为

class Single

{

private static Single=null;

private Single(){}

pulbic static Single getInstance()// →a ->b 线程

{

if(s==null)

{ synchronized(Single.class)

{

if(s==null)

S=new Single();

return s;

}

}

}

}

懒汉式与饿汉式有什么区别?

懒汉式的特定是实例的延迟加载,多线程访问出现安全问题,可以加同步代码块解决,稍微有些低效,可以用双重判断解决这个问题,加同步使用的锁是该类所属的字节码文件对象。

9.死锁: 嵌套锁

A锁装B锁,B锁装A锁

Cass MyLock

{

Static Object a=new Object();

Static Object b=new Object();

}

class Test implements Runnable()

{

private boolean flag;

Test(boolean flag)

{

this.flag=flag;

}

public void run()

{

if(flag)

{

Synchronized(MyLock.a)

{

System.out.println(“if a”);

Synchornized(MyLock.a)

{

System.out.println(“if b”);

}

}

}

else

{

Synchronized(MyLock.b)

{

System.out.println(“else b”);

Synchornized(MyLock.a)

{

System.out.println(“else a”);

}

}

}

}

Class LockTest

{

Public static void main(String[] args)

{

Thread t1=new Thread(new Test(true));

Thread t2=new Thread(new Test(false));

t1.start();

t2.start();

}

}

9、线程间通讯

线程间通讯:

其实就是多个线程在操作同一个资源,但是操作的动作不同。

notify() 唤醒

notifaAll()

都使用在同步中,因为对持有监视器(锁)的线程操作。

所以要使用在同步中,因为只有同步才有锁。

为什么这些操作线程的方法要定义在Object类中?

因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,

只有同一个锁上的被等待线程,可以被同一个锁notify唤醒。

不可以对不同锁中的线程进行唤醒。

也就是说,等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。

生产者和消费者问题

对于多个生产者和消费者,

为什么要定义while判断标记。

原因:让被唤醒的线程再一次判断标记。

为什么定义notifyAll,

因为需要唤醒对方线程。

因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的线程都在等待。

Jdk5.0 提供了多线程升级解决方案

将同步Synchronized替换成实现Lock操作

将Object中的wait,notify,notifyAll,用condition对象进行替换

该对象可以Lock,进行获取

可实现本方只唤醒对方

提供显式的锁机制,显式的锁对象的等待、唤醒操作机制,一个锁可产生多个Condition对象

Lock lock=new ReentrantLock()

Condition condition=lock.newCondition();

lock.lock();

try

{

condition_pro.await(); //生产者等待

……………

……………

flag=false;

condition_con.singal(); //唤醒消费者

}

Finally

{

lock.unlock(); //释放锁的操作一定要执行

}

10、停止线程

stop方法已经过时

如何停止线程?

只有一种,run方法结束。

开启多线程运行,运行代码通常是循环结构。

只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:

当线程处于冻结状态。

就不会读取到标记,那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结状态进行清除。

强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

Thread类提供该方法interrupt()。

11、守护线程

将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。

t.setDaemon(true);// 该方法必须在启动线程前调用。

t.start();

即当所有前台进程结束,守护线程也随之结束。

12、join方法

join:

当A线程执行到B线程的join的方法时,A就会等待。等B线程都执行完,A 才会执行。

Join可以用来临时加入线程执行。

13、优先级(5-10)设置抢cpu资源的频率

默认是5.

IllegalArgumentException - 如果优先级不在 MIN_PRIORITY 到

MAX_PRIORITY 范围内。

SecurityException - 如果当前线程无法修改该线程。

t.setPriority(Thread.MAX_PRIORITY)

yield方法

public static void yield()

暂停当前正在执行的线程对象,并执行其他线程。

操作系统第二章进程和线程复习题

第二章练习题 一、单项选择题 1.某进程在运行过程中需要等待从磁盘上读入数据,此时该进程的状态将( C )。 A. 从就绪变为运行; B.从运行变为就绪; C.从运行变为阻塞; D.从阻塞变为就绪2.进程控制块是描述进程状态和特性的数据结构,一个进程( D )。 A.可以有多个进程控制块; B.可以和其他进程共用一个进程控制块; C.可以没有进程控制块; D.只能有惟一的进程控制块。 3.临界区是指并发进程中访问共享变量的(D)段。 A、管理信息 B、信息存储 C、数据 D、 程序 4. 当__ B__时,进程从执行状态转变为就绪状态。 A. 进程被调度程序选中 B. 时间片到 C. 等待某一事件 D. 等待的事件发生 5. 信箱通信是一种( B )通信方式。 A. 直接通信 B. 高级通信

C. 低级通信 D. 信号量 6. 原语是(B)。 A、一条机器指令 B、若干条机器指令组成 C、一条特定指令 D、中途能打断的指令 7. 进程和程序的一个本质区别是(A)。 A.前者为动态的,后者为静态的; B.前者存储在内存,后者存储在外存; C.前者在一个文件中,后者在多个文件中; D.前者分时使用CPU,后者独占CPU。 8. 任何两个并发进程之间存在着(D)的关系。 A.各自完全独立B.拥有共享变量 C.必须互斥D.可能相互制约 9. 进程从运行态变为等待态可能由于(B )。 A.执行了V操作 B.执行了P 操作 C.时间片用完 D.有高优先级进程就绪 10. 用PV操作管理互斥使用的资源时,信号量的初值应定义为(B)。 A.任意整数 B.1 C.0 D.-1

第二章进程管理答案

第二章进程管理 一、单项选择题 1、顺序程序和并发程序的执行相比,()。 A.基本相同 B. 有点不同 C.并发程序执行总体上执行时间快 D.顺序程序执行总体上执行时间快 2、在单一处理机上,将执行时间有重叠的几个程序称为()。 A.顺序程序 B. 多道程序 C.并发程序 D. 并行程序 3、进程和程序的本质区别是()。 A.存储在内存和外存 B.顺序和非顺序执行机器指令 C.分时使用和独占使用计算机资源 D.动态和静态特征 4、在下列特性中,不是进程的特性的是()。 A. 异步性 B. 并发性 C. 静态性 D. 动态性 5 A 6 A. 7 A. 8 A. 9 A. 10 A. 11 A. 12。 A. 13 A. 14 A. 15 A. 16、在操作系统中,对信号量S的P原语操作定义中,使进程进入相应阻塞队列等待的条件是()。 A. S>0 B. S=0 C. S<0 D. S≠0 17、信号量S的初值为8,在S上执行了10次P操作,6次V操作后,S的值为()。 A.10 B.8 C.6 D.4 18、在进程通信中,使用信箱方式交换信息的是()。 A.低级通信B.高级通信C.共享存储器通信D.管道通信 19.( )必定会引起进程切换。A.一个进程被创建后进入就绪态B.一个进程从运行态变成等待态c.一个进程从运行态变成就绪态 D.一个进程从等待态变成就绪态 20、操作系统使用( )机制使计算机系统能实现进程并发执行,保证系统正常工作。 A.中断B.查询c.同步D互斥 21.对于一个单处理器系统来说,允许若干进程同时执行,轮流占用处理器.称它们为()的。 A.顺序执行 B.同时执行c.并行执行D.并发执行

多线程小测验

一、单选题(每题3分,共计15分) 1、在以下哪种情况下,线程进入就绪状态? A、线程调用了sleep()方法时 B、线程调用了join()方法 C、线程调用了yield()方法时 D、线程调用了notify()方法 2、如果线程正处于运行状态,则它可能到达的下一个状态是( ) A、只有终止状态 B、只有阻塞状态和终止状态 C、可运行状态,阻塞状态,终止状态 D、其他所有状态 3、以下哪种原因不会导致线程暂停运行。 A、等待 B、阻塞 C、休眠 D、挂起及由于I/O操作而阻塞 4、Thread类位于下列哪个包中? A、java.io B、https://www.wendangku.net/doc/cc8800368.html,ng C、java.util D、java.awt 5、线程调用sleep()方法后,该线程将进入以下哪种状态? A、就绪状态 B、运行状态

C、阻塞状态 D、死亡状态 二多选题(每题5分,共计25分) 1、对于通过实现Runnable接口创建线程,下面说法正确的有哪些? A、适合多个相同程序代码的线程去处理同一个资源的情况 B、把线程同程序代码、数据有效的分离,很好的体现了面向对象的设计思想 C、可以避免由于Java的单继承带来的局限性 D、编写简单,可以不通过Thread类直接创建线程 2、下面四个选项中,哪些是线程进入阻塞状态的原因? A、线程试图获取某个对象的同步锁,而该锁被其它线程持有 B、线程调用了另一个线程的join()方法 C、当线程调用了一个阻塞式的IO方法 D、线程调用了setDaemon(boolean b)方法 3、对于wait()方法,下面说法正确的是? A、wait()方法的调用者是同步锁对象 B、wait()方法使线程进入等待状态 C、调用同一锁对象的notify()或notifyAll()方法可以唤醒调用wait()方法等待的线程 D、调用wait()方法的线程会释放同步锁对象 4、对于死锁的描述,下面四种说法正确有哪些? A、当两个线程互相等待对方释放同步锁时会发生死锁 B、Java虚拟机没有检测和处理死锁的措施 C、一旦出现死锁,程序会发生异常 D、处于死锁状态的线程处于阻塞状态,无法继续运行

不同操作系统下Java线程的区别

java的线程概念与操作系统的线程概念是不同的,java的线程概念差不多与windows线程概念一致,但是java既然目标是跨平台语言,那么它的线程机制概念是在所有平台上都是一样的,但是实际实现又不是如此,这要从进程与线程的概念中谈起: 首先在windows系列系统中,进程所拥有的内存空间都是独立的,此进程所持有的内存其它进程是不可以直接访问的,而且在windows系统内部一个进程就是一个运行的运用程序,而为了解决应用程序内部的并行问题便有了线程的概念,线程没有自我独立的内存空间,在一个进程中所有的线程共享这个进程所持有的内存空间。 而在某些Unix系统当中,进程所持有的内存空间是可以被其他进程进行访问的,而且一个运用程序可能不止一个进程,这样的系统没有线程的概念,运用的并行问题有多个进程协调来解决。 java为了实现平台无关性,必须解决这样一个问题,因此java建立了一套自己的进程与线程机制,这套机制与windows系统的颇为相似,但是底层实现确实根据不同平台的机制进行实现,比如windows下的线程机制就是利用windows本身的线程机制加上某些改进进行处理的,而某些没有线程的Unix系统则是用进程来替代线程进行实现的,然后在其中确立一个主进程来替代自身进程。虽然这样的实现解决了大部分的线程平台无关性,但是也有些无法解决的,比如线程优先级,windows下线程是有优先级的,但是某些Linux系统,某些Unix系统,进程与线程直接不区分优先级,因此优先级在每个系统下的表现形式就不一样,例如低优先级的进程可能在windows下被饿死,但是在linux下,根本就无法感觉它优先级较低,还有,在建立一个线程与杀死一个线程运用所带来的开销也会不同,在windows下建立或杀死线程可能是不需要什么开销的,但是在没有线程概念的进程行操作系统中,杀死或者建立线程可能带来巨大开销

优先级倒置问题

6.3.1 优先级倒置 很多实时系统都实现了线程优先级机制,每个线程被分配一个优先级,优先级高的线程只要具备了运行的条件,或者说进入了就绪态,就可以立即执行。除了优先级最高的那个线程外,其他线程在执行过程中随时都可能停下来,让给优先级更高的线程先执行。抢占式调度策略能保证系统的实时性。 由于多个线程共享资源,在采用基于优先级调度策略时会出现较低优先级的线程先于高优先级线程执行的情况,即优先级倒置(priority inversion)问题。优先级倒置可能使实时性要求高的线程错过临界期限(critical deadline),从而导致系统崩溃。 在采用基于优先级的调度策略,一旦两个线程共享了资源,那么其中之一通常具有较高的优先级。高优先级的线程期望一旦准备就绪就能运行,但当高优先级线程就绪,而低优先级线程正在使用共享资源时,高优先级线程必须等待,直到低优先级线程完成对共享资源的操作。这时,我们称高优先级线程被挂起。当高优先级线程挂起时,中优先级的线程抢先了正在使用共享资源的低优先级线程,此时高优先级线程已准备就绪并等待运行,但中优先级线程此刻正在运行,这时就出现了优先级倒置问题。 下图以三个不同优先级的线程为例描述一个优先级倒置的示例。高优先级线程H 和低优先级线程L 要共享资源R,为了保证数据的完整性,它们需要通过信号量S 来保证对临界资源的互斥访问。线程M 的优先级介于H 和L 之间。 图6.1 一个优先级倒置的示例 (1)低优先级线程L 取得信号量S 的所有权,即做了P 操作,但还没有做V 操作。(2)线程H 的优先级高于线程L,操作系统内核通过调度程序,将线程L 切换出去,将线程H 置为运行态。 (3)线程H 执行到中途需要访问共享资源R,必须先对信号量S 做P 操作。因为此信号量目前还没有恢复,于是线程H 阻塞在信号量S 上。 (4)线程L 重新被切换到运行态。 (5)此时线程M 进入到就绪态,因为线程M 的优先级高于任务L,于是内核进行线程切换,将线程M 置为运行态。 (6)线程M 执行结束后,线程L 恢复执行。 (7)线程L 释放共享资源R,即对信号量做V 操作。线程H 获得信号量S 的所有权才得以继续执行。

操作系统课程设计之线程

/* 说明:本程序中,默认以tcb下标为就绪队列,即从tcb[0]~tcb[NTCB-1]为轮转执行,程序中出现的id均为线程内部标识,即tcb的下标*/ #include #include /* 包含malloc()的头文件*/ #include #include /* 包含strcmp(),strcpy()的头文件*/ #define GET_INDOS 0X34 /* 参见实验指导书*/ #define GET_CRIT_ERR 0X5D06 /* 参见实验指导书*/ #define NTCB 5 /* NTCB是系统允许的最多线程数,也就是允许的线程控制块最大数*/ #define NBUF 5 /* 空闲缓冲区的数量*/ #define NTEXT 20 /* 在线程间传送信息时,信息的上限*/ #define FINISHED 0 /* 表示线程处于终止态或TCB是空闲状态*/ #define RUNNING 1 /* 表示线程处于运行态*/ #define READY 2 /* 表示线程处于就绪态*/ #define BLOCKED 3 /* 表示线程处于阻塞态*/ int current = 0; /* 当前TCB,初始=0 */ int timecount = 0; /* 时间计数*/ int TL = 1; /* 时间片大小*/ char far *indos_ptr = 0; /* 该指针变量存放INDOS标志的地址*/ char far *crit_err_ptr = 0; /* 该指针变量存放严重错误标志的地址*/ /*记录型信号量的定义,参见课本51 页*/ typedef struct{ int value; /* 资源数目*/ struct TCB *wq; /* 线程链表指针,链接所有等待线程*/ } semaphore; struct TCB{ unsigned char *stack; /* 线程堆栈的起始地址*/ unsigned ss; /* 堆栈段址*/ unsigned sp; /* 堆栈指针*/ char state; /* 线程状态:执行、就绪、阻塞*/ char name[10]; /* 线程的外部标识符*/ struct buffer *mq; /* 消息队列队首指针*/ semaphore mutex; /* 消息队列互斥信号量*/ semaphore sm; /* 消息队列资源信号量,用于实现同步*/

北大操作系统高级课程-陈向群作业-XV6进程线程

阅读代码: 1.基本头文件: types.h param.h memlayout.h defs.h x86.h asm.h mmu.h elf.h 2.进程线程部分: vm.c proc.h proc.c swtch.S kalloc.c 以及相关其他文件代码 强调一下:由于内存管理部分还没有学到,所以请同学们遇到相关的代码和问题时,先将问题记录下来,到学过之后,再结合进程线程管理部分进行深入学习,最后要求对XV6有整体的理解。 请大家围绕如下一些问题阐述原理课的相关内容,以及XV6中是如何实现的。 1.什么是进程,什么是线程?操作系统的资源分配单位和调度单位分别是什么?XV6中的 进程和线程分别是什么,都实现了吗? 答:进程是在多道程序系统出现以后,为了描述系统内部各作业的活动规律而引进的概念。进程有3个基本状态,运行状态、就绪状态和等待状态(或称阻塞状态);进程只能由父进程建立,系统中所有的进程形成一种进程树的层次体系;挂起命令可有进程自己和其他进程发出,但是解除挂起命令只能由其他进程发出。进程是具有独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的独立单位。 线程可称为轻量级的进程,是操作系统可以运行调度的最小单位。线程是进程内的一个相对独立的可执行的单元。若把进程称为任务的话,那么线程则是应用中的一个子任务的执行。 不论操作系统中是否引入了线程,操作系统中资源分配的基本单位都是进程。如果操作系统没有引入线程那么进程就是调度的基本单位。线程并不独立拥有资源,它仅仅分配了一些运行必备的资源。一个进程中的多个线程共同分享进程中的资源。在引入了线程的操作系统中,线程就变成了调度的基本单位,进程中的部分线程阻塞并不代表该线程被阻塞。 xv6操作系统实现了一个基于进程(没有实现线程)的简单进程管理机制。通过对proc.h 文件的阅读了解到xv6的进程中定义了一个context结构,一个枚举类型proc_state定义了UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE 这6种进程的状态,proc结构定义了进程控制块的内容,cpu结构定义了寄存器和栈指针。 2.进程管理的数据结构是什么?在Windows,Linux,XV6中分别叫什么名字?其中包含哪 些内容?操作系统是如何进行管理进程管理数据结构的?它们是如何初始化的? 答:进程管理的数据结构是进程控制块(PCB)。在Linux中进程控制块的结构是由一个叫task_struct的数据结构定义的,ask_struct存在/include/ linux/sched.h中,其中包括管理进程

Linux内核线程优先级设置的方法介绍

Linux内核线程优先级设置的方法介绍 个人理解,内核级线程和进程是一样的,前者与POSIX线程(pthread)有很大的区别。因此,内核的进程调度策略和系统调用也适用于内核级线程。 调度策略有三种: 1.SCHED_NORMAL 非实时调度策略,默认情况下是100~139,由nice值决定; 2.SCHED_FIFO实时调度策略,先到先服务。一旦占用cpu则一直运行。一直运行直到有更高优先级任务到达或自己放弃 3.SCHED_RR实时调度策略,时间片轮转。当进程的时间片用完,系统将重新分配时间片,并置于就绪队列尾。同样可以被高优先级抢占。 两种实时优先级范围在0至MAX_RT_PRIO-1之间,默认为0到99。 相关的系统调用(来自于LKD,不同内核可能有所不同): nice()设置进程的nice值sched_setscheduler()设置进程的调度策略sched_getscheduler()获取进程的调度策略sched_setparam()设置进程的实时优先级sched_getparam()获取进程的实时优先级sched_get_priority_max()获取实时优先级的最大值sched_get_priority_min()获取实时优先级的最小值sched_rr_get_interval()获取进程的时间片值sched_setaffinity()设置进程的处理器的亲和力sched_getaffinity()获取进程的处理器的亲和力sched_yield()暂时让出处理器 设置时需要用到struct sched_param这个结构。 以下为我写的内核线程中的部分代码:代码如下: struct sched_param param; param.sched_priority = 99; sched_setscheduler(current, SCHED_FIFO, ?m)//出错时返回-1

线程的优先级和线程让步yield

2、线程的优先级和线程让步yield() 线程的让步是通过Thread.yield()来实现的。yield()方法的作用是:暂停当前正在执行的线程对象,并执行其他线程。 要理解yield(),必须了解线程的优先级的概念。线程总是存在优先级,优先级范围在1~10之间。JVM线程调度程序是基于优先级的抢先调度机制。在大多数情况下,当前运行的线程优先级将大于或等于线程池中任何线程的优先级。但这仅仅是大多数情况。 注意:当设计多线程应用程序的时候,一定不要依赖于线程的优先级。因为线程调度优先级操作是没有保障的,只能把线程优先级作用作为一种提高程序效率的方法,但是要保证程序不依赖这种操作。 当线程池中线程都具有相同的优先级,调度程序的JVM实现自由选择它喜欢的线程。这时候调度程序的操作有两种可能:一是选择一个线程运行,直到它阻塞或者运行完成为止。二是时间分片,为池内的每个线程提供均等的运行机会。 设置线程的优先级:线程默认的优先级是创建它的执行线程的优先级。可以通过setPriority(int newPriority)更改线程的优先级。例如: Thread t = new MyThread(); t.setPriority(8); t.start(); 线程优先级为1~10之间的正整数,JVM从不会改变一个线程的优先级。然而,1~10之间的值是没有保证的。一些JVM可能不能识别10个不同的值,而将这些优先级进行每两个或多个合并,变成少于10个的优先级,则两个或多个优先级的线程可能被映射为一个优先级。 线程默认优先级是5,Thread类中有三个常量,定义线程优先级范围: static int MAX_PRIORITY 线程可以具有的最高优先级。 static int MIN_PRIORITY 线程可以具有的最低优先级。 static int NORM_PRIORITY 分配给线程的默认优先级。 3、Thread.yield()方法 Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。 yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。 结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。 4、join()方法 Thread的非静态方法join()让一个线程B“加入”到另外一个线程A的尾部。在A执行完毕之前,B不能工作。例如: Thread t = new MyThread(); t.start(); t.join(); 另外,join()方法还有带超时限制的重载版本。例如t.join(5000);则让线程等待5000毫秒,如果超过这个时间,则停止等待,变为可运行状态。 线程的加入join()对线程栈导致的结果是线程栈发生了变化,当然这些变化都是瞬时的。下面给示意图:小结 到目前位置,介绍了线程离开运行状态的3种方法:

java练习题-多线程

多线程 一、判断题 1.如果线程死亡,它便不能运行。(√) 2.在Java中,高优先级的可运行线程会抢占低优先级线程。(√) 3.线程可以用yield方法使低优先级的线程运行。(×) 4...程序开发者必须创建一个线程去管理内存的分配。(×) 5.一个线程在调用它的start方法,之前,该线程将一直处于出生期。(√) 6.当调用一个正在进行线程的stop( )方法时,该线程便会进入休眠状态。(×) 7.一个线程可以调用yield方法使其他线程有机会运行。(√) 二、选择题 1.Java语言中提供了一个▁d▁线程,自动回收动态分配的内存。 A.异步 B.消费者 C.守护 D.垃圾收集 2.Java语言避免了大多数的▁c▁错误。 A.数组下标越界 B.算术溢出 C.内存泄露 D.非法的方法参数 3.有三种原因可以导致线程不能运行,它们是▁acd▁。 A.等待 B.阻塞 C.休眠 D.挂起及由于I/O操作而阻塞 4.当▁a▁方法终止时,能使线程进入死亡状态。 A.run B.setPrority C.yield D.sleep 5.用▁b▁方法可以改变线程的优先级。 A.run B.setPrority C.yield D.sleep 6.线程通过▁c▁方法可以使具有相同优先级线程获得处理器。 A.run B.setPrority C.yield D.sleep

7.线程通过▁d▁方法可以休眠一段时间,然后恢复运行。 A.run B.setPrority C.yield D.sleep 8.方法resume( )负责重新开始▁d▁线程的执行。 A.被stop( )方法停止 B.被sleep( )方法停止 C.被wait( )方法停止 D.被suspend( )方法停止 9.▁BCD▁方法可以用来暂时停止当前线程的运行。 A.stop( ) B.sleep( ) C.wait( ) D.suspend( ) 三、简述题 1.简述程序、进程和线程之间的关系?什么是多线程程序? 答:多线程是多个线程同时在执行。这些线程的执行是并发的,在逻辑上是同时进行,各个线程的控制流彼此独立。 2.线程有哪几个基本状态?它们之间如何转化?简述线程的生命周期。 答:新生状态—就绪状态—运行状态—等待状态—休眠状态—阻塞状态—死亡状态使用new创建新线程时,为新生状态;调用已经完成创建的线程中的start()方法之前,处于就绪状态;调用start()方法之后,处于运行状态;当线程需要获得对象的内置锁,而该锁正被其他线程拥有时,处于阻塞状态; 3.试简述Thread类的子类或实现Runnable接口两种方法的异同? 答: class Threadx1 extends Thread class Threadx2 implements Runnable

操作系统实验报告(包括线程,进程,文件系统管理,linux+shell简单命令)

操作系统实验报告 班级:030613 学号:03061331 姓名:裴帅帅

实验一:进程的建立 一、实验内容 创建进程及子进程,在父子进程间实现进程通信,创建进程并显示标识等进 程控制块的属性信息,显示父子进程的通信信息和相应的应答信息。 使用匿名管道实现父子进程之间的通信。 二、源程序 1、创建匿名管道 SECURITY_ATTRIBUTES sa; sa.bInheritHandle=true; sa.lpSecurityDescriptor=NULL; sa.nLength=sizeof(SECURITY_ATTRIBUTES); if(!CreatePipe(&m_hRead,&m_hWrite,&sa,0)) { MessageBox("创建匿名管道失败"); return false; } 2、创建子进程 STARTUPINFO si; ZeroMemory(&si,sizeof(STARTUPINFO)); si.cb=sizeof(STARTUPINFO); si.dwFlags=STARTF_USESTDHANDLES; si.hStdInput=m_hRead; si.hStdOutput=m_hWrite; si.hStdError=GetStdHandle(STD_ERROR_HANDLE); if(!CreateProcess(NULL,"子 进.exe",NULL,NULL,true,0,NULL,NULL,&si,&pi)) { MessageBox("创建子进程失败"); CloseHandle(m_hRead); CloseHandle(m_hWrite); m_hRead=NULL; m_hWrite=NULL; return; } 3、销毁子进程 if(m_hRead) CloseHandle(m_hRead);

LabVIEW程序中的线程线程的优先级

LabVIEW 程序中的线程3 - 线程的优先级 三、线程的优先级 在VI 的属性设置面板VI Properties -> Execution 中还有一个下拉选项控件是用来设置线程优先级的(Priority)。这一选项可以改变这个VI 运行线程的优先级。 优先级设置中共有六项,其中前五项是分别从低到高的五个优先级。优先级越高,越容易抢占到CPU 资源。比如你把某个负责运算的VI 的优先级设为最高级(time critical priority),程序在运行时,CPU 会更频繁地给这个VI 所在线程分配时间片段,其代价是分配给其它线程的运算时间减少了。如果这个程序另有一个线程负责界面刷新,那么用户会发现在把执行线程的优先级提高后,界面刷新会变得迟钝,甚至根本就没有响应。 优先级设置的最后一项是subroutine,它与前五项别有很大的不同。严格的说subroutine 不能作为一个优先级,设置subroutine 会改变VI 的一些属性: 设置为subroutine 的VI 的前面板的信息会被移除。所以这样的VI 不能用作界面,也不能单独执行。 设置为subroutine 的VI 的调试信息也会被移除。这样的VI 无法被调试。 当程序执行到被设置为subroutine 的VI 的时候,程序会暂时变为单线程执行方式。即程序在subroutine VI 执行完之前,不会被别的线程打断。 以上的三点保证了subroutine VI 在执行时可以得到最多的CPU 资源,某些作为关键运算的VI,又不是特别耗时的,就可以被设置为subroutine 以提高运行速度。比如有这样一个VI,他的输入是一个数值数组,输出是这组数据的平均值。这个运算在程序中需要被尽快完成,以免拖延数据的显示,这个VI 就是一个蛮适合的subroutine VI。 在设置VI 优先级的时候有几点需要注意的。 提高一个VI 的优先级一般不能显著缩短程序的运行时间。提高了优先级,它所需要的CPU 时间还是那么多,但是CPU 被它占用的频率会有所提高。 高优先级的VI 不一定在低优先级VI 之前执行。现在常用的多线程操作系统采用的都是抢占式方式,线程优先级别高,抢到CPU 的可能性比低级别的线程大,但也不是绝对的。 使用subroutine 时要格外注意,因为他会让你的程序变成单线程方式执行,这在很多情况下反而会降低你的程序的效率。比如一个VI 并非只是用来运算,它还需要等待其它设备传来的数据,这样的VI 就绝对不能被设置为subroutine。现在多核CPU 已经很流行了,在这样的计算机上,单线程运行的程序通常比多线程效率低,这也是需要考虑的。

操作系统课后习题答案 2 进程答案

习题2 进程、线程管理 一、选择题 题号 1 2 3 4 5 6 7 8 9 10 答案 B B D C D C A B D C 题号 11 12 答案 A A 二、综合题 2、答:在多道程序环境下,允许多个程序并发执行,这就导致了在操作系统中引入了“进 程”。进程是随着操作系统中分时思想的提出而引出的。进程是一个可并发执行的具有 独立功能的程序在某个数据集合的一次执行过程,它是操作系统进行资源分配和保护的 基本单位。 ①进程和程序的最大区别就是进程是程序的一次执行过程,它是一个动态概念。程序 是以文件形式存放在磁盘上的代码序列,它是一个静态概念。 ②进程能够并发执行。在同一段时间内,并发执行的若干进程共享一个处理机,各个 进程按照不同的推进速度运行。进程状态及其转换可以很好地描述并发执行进程的执行过 程。

③进程是计算机系统资源分配的基本单位,程序不能作为一个独立单位运行和申请系 统资源。 ④进程由含有代码和数据的用户地址空间、进程控制块和执行栈区等部分组成,而程 序只由静态代码组成。 ⑤进程和程序之间是多对多的关系。一个程序可被多个进程共用,一个进程在其活动 中又可调用若干个程序。 2、答: 原语是由若干条机器指令组成的、用于完成一定功能的一个过程。原语不可分割,其执 行期间不充许被中断,要么从头到尾执行一遍,要么全不执行。原语的特征保证其在执行过 程中不受外界因素的影响。 原语的一般实现方法是以系统调用的方式提供原语接口,原语在执行过程中采用屏蔽中断的 方式来保证其不能被中断。原语常驻内存,只在核心态下运行。通常情况下,原语只提供给 系统进程或系统服务器使用。 3、答: 传统操作系统通过进程的并发执行提高了系统资源利用率和作业吞

多线程编程中应该注意的问题

多线程编程中应该注意的问题 1. 线程的优先级 多线程编程中要注意协调好各个线程的优先级。一般来说,控制线程的优先级要高于Worker 线程。这样做,可以保证Client (最终用户或者其他模块)尽快得到响应。当控制线程是与最终用户交互的界面线程时更应如此,如果界面线程优先级较低,界面可能较长时间没有反应,用户很可能会怀疑命令是不是还没有开始执行。下面两张图给出了控制线程优先级不同对Client 造成不同响应时间的对比。 控制线程低优先级,Worker 线程高优先级 Fig 1.1 控制线程优先级低,对用户响应时间较长 控制线程高优先级,Worker 线程低优先级 Fig 1.2 控制线程优先级高,对用户响应时间较短

2.防止栈溢出 这个问题不只存在在多线程编程中。防止栈溢出可以参考下面几条建议: 1)不在函数体内定义特别大的栈变量,必须要定义的时候,可以使用new在堆上分配。 2)传递参数时,大的参数(如结构体,类)使用按指针传递,小的参数(如基本数据 类型)使用按值传递。 堆栈 Fig 2.1 大对象作为参数时,按值传递的过程 堆栈 Fig 2.2 大对象作为参数时,按指针传递的过程。 由Fig 2.1和Fig 2.2可以看出,对于较大的对象,按指针的传递的资源消耗较小, 空间上,仅需把一个指针压栈;时间上,省去了拷贝构造函数的调用。所以在传递 大的对象时,应该使用按指针传递。

堆栈 Fig 2.3 参数为基本类型时,按值传递的过程 1.取地址 堆栈 3.将创建的拷贝压入堆栈。 2.创建指针的一个拷贝 Fig 2.4 参数为基本类型时,按指针传递的过程。 对比Fig 2.3和Fig 2.4可以看出,对于基本数据类型,按指针传递的方法反而会消耗较多的时间,而且当参数所占的字节数小于一个指针所占的字节数(4个字节)时,按指针传递也会消耗较多的空间。所以当参数为基本数据类型时,应该使用按值传递。

操作系统中的进程线程与Java的多线程

操作系统中的进程线程与Java 的多线程 OS ofthe Process 、ThreadandJavamultithread HuZhi qin Ningxia TV University ,Yinchuan 750002, China :This paper reports a study on detailed expositions about the relationship among the process , threading and multi-threaded java , analyzing from the basic concept of the process, threading and multi-threading , demonstrations are also offered to show the applications of thread in the procedures Java 、creation of threading and running. 1 进程与线程操作系统中进程是指特定的代码序列在指定数据集合上的一次执行活动,是指并行程序的一次执行过程,在Windows95中,就是一个EXE文件的执行过程。是一个动态概念,具有动态属性,每一个进程都是由内核对象和地址空间所组成的,内核对象可以让系统在其内存放有关进程的统计信息并使系统能够以此来管理进程,而地址空间则包括了所有程序模块的代码和数据以及线程堆栈、堆分配空间等动态分配的空间。 通俗点讲,进程就是正在计算机上运行的可执行文件针对特 定的输入数据的一个实例,从此意义上讲,进程应包含三部分内容,即:进程=PCB程序段+数据(PCB进程控制块),同一个可执行 程序文件如果操作不同的输入数据就是两个不同的进程。 进程理解为一个线程容器,线程不能独立存在,它必须隶属

线程优先级

线程优先级 每个线程都有一个“优先级”,范围是0~31,0为最低优先级,31为最高优先级。当系统决定哪个线程需要调度的时候,首先查看是否存在优先级为31的可调度线程,如果存在,就从中选择一个进行调度。当该线程的时间片到达之后,系统查看是否存在另一个优先级为31的可调度线程,如果存在,就调度它。 只要有一个可调度的优先级为31的线程存在,那么系统绝对不会调度优先级为0~30的线程,这样会导致其他线程“饥饿”。 高优先级线程往往“打断”低优先级线程的执行。比如,当一个优先级为15的线程正在运行,如果此时系统发现一个优先级比15高的线程可以调度,那么该高优先级线程会“打断”那个低优先级线程的执行,哪怕低优先级的时间片才过了一半。 另外,当系统引导的时候,系统创建一个特殊的线程,称为“zero page”(0页)线程,该线程是整个系统中唯一一个优先级为0(最低)的线程。当系统没有任何线程需要执行的时候,该线程负责将系统中所有RAM页面清零(也就是资源回收)。 线程优先级有一个抽象层的概念。 由于一些历史的原因,微软并没有将线程调度程序的行为完全固定下来。微软没有让应用程序充分利用调度程序的特性。微软宣称这个调度程序的行为是变化,在编程的时候需要注意。 由这几点可见,你的应用程序可以有自己的调度特性。 Windows API充分反映了系统调度的一个抽象层。如此,就不会直接与系统的调度程序通信,相反,可以调用API函数,根据系统的版本的不同转换这些参数。这一层,就是线程优先级的抽象层。 下面详细叙述这个抽象层究竟有哪些内容。 对于进程而言,Windows有一个“优先级类”的概念。这些优先级类作用与进程中的所有线程。Windows 2000/XP/2003/Vista支持6个“优先级类”: 1、Real-time:实时 2、High:高 3、Above normal:高于标准 4、Normal:标准 5、Below normal:低于标准 6、Idle:空闲。 一个进程应该避免使用“实时”优先级类,因为使用该优先级类会导致其他进程中的线程很难被调度,甚至会打断或者抢占系统线程的执行。“高”优先级类也应该尽量避免,除非有特殊的工作需要使用这个优先级。 当一个进程的“优先级类”被确定以后,就只需要考虑该进程内部各个线程之间的优先级关系。 对于进程中的线程而言,有一个“相对线程优先级”的概念,这可以决定一个进程中多个线程之间的优先级关系。 Windows支持7种“相对线程优先级”: 1、Time-critical:关键时间(最高的相对线程优先级) 2、Heightest:最高(翻译是这么翻译,但是并不是最高的相对线程优先级) 3、Above normal:高于标准 4、Normal:标准 5、Below normal:低于标准

操作系统实验线程的同步

操作系统实验线程的同步 部门: xxx 时间: xxx 整理范文,仅供参考,可下载自行编辑

实验六线程的同步 1、实验目的 (1)进一步掌握Windows系统环境下线程的创建与撤销。 (2)熟悉Windows系统提供的线程同步API。 (3)使用Windows系统提供的线程同步API解决实际问题。 2、实验准备知识:相关API函数介绍 ①等待对象 等待对象

·Waitable timer:定时器。 原型: DWORD WaitForSingleObject( HANDLE hHandle, // 对象句柄 DWORD dwMilliseconds // 等待时间 ); 参数说明: (1)hHandle:等待对象的对象句柄。该对象句柄必须为SYNCHRONIZE访问。 dwMilliseconds:等待时间,单位为ms。若该值为 0,函数在测试对象的状态后立即返回,若为 INFINITE,函数一直等待下去,直到接收到一个信 号将其唤醒,如表2-1所示。p1EanqFDPw 返回值: 如果成功返回,其返回值说明是何种事件导致函数返回。 表2-1 函数描述 用法举例: Static HANDLE hHandlel = NULL。

windows核心编程(第五版)笔记第七章线程调度优先级(threadsched

Windows核心编程(第五版)笔记第七章线程调度、优先 级(Thread Sched... Windows核心编程(第五版)笔记第七章线程调度、优先级(Thread Scheduling,Priorities and Affinity) 第七章线程调度、优先级、亲和力 1.挂起和恢复线程 (1)ResumeThread 被挂起的线程不会被调度,只有线程调用ResumeThread()的次数等于SuspendThread()时,线程才会被调度。 线程可以Suspend自已但是不能Resume自已。因为被挂起后不会被调度,从而不会执行线程函数内的代码. (2)SuspendThread 挂起线程时一定要小心必须明确知道线 程在干什么才能决定是否挂起线程。因为当线程正在堆分配内存时,它会给这个堆加上锁。 此时如果将线程挂起,其它线程若想在堆上分配内存则会进入无限等待直到堆的锁被挂起的线程解

开。从而导致死锁。 2.挂起和恢复进程 Windows中并不存在挂起和恢复进程的概念。因为Windows中是以线程为单位来调度和分配CPU的。进程只相当于是一个承载线程的容器,系统不会给进程分配 任何CPU. 我们可以把挂起进程理解为挂起进程中所 有的线程。Windows并没有提供此类API,但是我们可以通过CreateToolhelp32Snapshot()来实现我们自制的SuspendProcess(). 因为CreateToolhelp32Snapshot只是创建某 个进程在某一时刻的快照(如进程占有的内存,进程中有多少正在运行的线程)。 然后通过Thread32First()和Thread32Next() 来遍历快照中所得的所有线程。 这么做容易出一些问题比如通过 Thread32Next()取得线程ID后线程可能立刻就终止了。同样随时会有新的线程产生,而快照中不会反应有出新产生的线程,

计算机操作系统-进程原理之线程

1 计算机操作系统(Operating Systems) 进程原理之线程 Chen Genlang Email:cgl@https://www.wendangku.net/doc/cc8800368.html, Institute of Computer Application 2009/9/1

2 线程的出现 每个人在人生的某个时间,都希望自己能够分身,从而完成某件不可能完成的事。而进程也是一样,它也希望在某些时候能够分身,从而完成更加复杂的使命。 线程就诞生了!

3 一般来说,当运行一个应用程序的时候,就启动了一个进程,当然有些会启动多个进程。启动进程的时候,操作系统会为进程分配资源,其中最主要的资源是内存空间,因为程序是在内存中运行的。 在进程中,有些程序流程块是可以乱序执行的,并且这个代码块可以同时被多次执行。实际上,这样的代码块就是线程体。 线程是进程中乱序执行的代码流程。当多个线程同时运行的时候,这样的执行模式成为并发执行。

4 假如我们把整条道路看成是一个“进程”的话,那么 图中由白色虚线分隔开来的各个车道就是进程中的各个“线程”了: 这些线程(车道)共享了进程(道路)的公共资源(土地资源) 这些线程(车道)必须 依赖于进程(道路), 也就是说,线程不能 脱离于进程而存在(就 像离开了道路,车道 也就没有意义了)。

5 这些线程(车道)之间可以并发执行(各个车道你走你的,我走我的),也可以互相同步(某些车道在交通灯亮时禁止继续前行或转弯,必须等待其它车道的车辆通行完毕); 这些线程(车道)之间依靠代码逻辑(交通灯)来控制运行,一旦代码逻辑控制有误(死锁,多个线程同时竞争唯一资源),那么线程将陷入混乱,无序之中。 这些线程(车道)之间谁先运行是未知的,只有在线程刚好被分配到CPU时间片(交通灯变化)的那一刻才能知道。 总之:一个进程至少有一个线程,但也可以有多个线程。

操作系统精髓与设计原理-第4章 线程_对称多处理和微内核

第四章线程、对称多处理和微内核 复习题: 4.1表3.5列出了在一个没有线程的操作系统中进程控制块的基本元素。对于多线程系统, 这些元素中那些可能属于线程控制块,那些可能属于进程控制块? 答:这对于不同的系统来说通常是不同的,但一般来说,进程是资源的所有者,而每个线程都有它自己的执行状态。关于表3.5中的每一项的一些结论如下:进程标识:进程必须被标识,而进程中的每一个线程也必须有自己的ID。处理器状态信息:这些信息通常只与进程有关。进程控制信息:调度和状态信息主要处于线程级;数据结构在两级都可出现;进程间通信和线程间通信都可以得到支持;特权在两级都可以存在;存储管理通常在进程级;资源信息通常也在进程级。 4.2请列出线程间的模式切换比进程间的模式切换开销更低的原因。 答:包含的状态信息更少。 4.3在进程概念中体现出的两个独立且无关的特点是什么? 答:资源所有权和调度/执行。 4.4给出在单用户多处理系统中使用线程的四个例子。 答:前台和后台操作,异步处理,加速执行和模块化程序结构。 4.5哪些资源通常被一个进程中的所有线程共享? 答:例如地址空间,文件资源,执行特权等。 4.6列出用户级线程优于内核级线程的三个优点。 答:1.由于所有线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核模式的特权,因此,进程不需要为了线程管理而切换到内核模式,这节省了在两种模式间进行切换(从用户模式到内核模式;从内核模式返回用户模式)的开销。2.调用可以是应用程序专用的。一个应用程序可能倾向于简单的轮询调度算法,而另一个应用程序可能倾向于基于优先级的调度算法。调度算法可以去适应应用程序,而不会扰乱底层的操作系统调度器。3.用户级线程可以在任何操作系统中运行,不需要对底层内核进行修改以支持用户级线程。线程库是一组供所有应用程序共享的应用级软件包。 4.7列出用户级线程相对于内核级线程的两个缺点。 答:1.在典型的操作系统中,许多系统调用都会引起阻塞。因此,当用户级线程执行一个系统调用时,不仅这个线程会被阻塞,进程中的所有线程都会被阻塞。2.在纯粹的用户级进程策略中,一个多线程应用程序不能利用多处理技术。内核一次只把一个进程分配给一个处理器,因此一次进程中只能有一个线程可以执行。 4.8定义jacketing。 答:Jacketing通过调用一个应用级的I/O例程来检查I/O设备的状态,从而将一个产生阻塞的系统调用转化为一个不产生阻塞的系统调用。 4.9简单定义图4.8中列出的各种结构。 答:SIMD:一个机器指令控制许多处理部件步伐一致地同时执行。每个处理部件都有一个相关的数据存储空间,因此,每条指令由不同的处理器在不同的数据集合上执行。 MIMD:一组处理器同时在不同的数据集上执行不同的指令序列。主/从:操作系统内核总是在某个特定的处理器上运行,其他处理器只用于执行用户程序,还可能执行一些操作系统实用程序。SMP:内核可以在任何处理器上执行,并且通常是每个处理器从可用的进程或线程池中进行各自的调度工作。集群:每个处理器都有一个专用存储器,而且每个处理部件都是一个独立的计算机。 4.10列出SMP操作系统的主要设计问题。 答:同时的并发进程或线程,调度,同步,存储器管理,可靠性和容错。

相关文档