程序 -- 进程 -- 线程 -- 多线程

程序 -- 进程 -- 线程

(OS给出的)进程说明:进程作为资源分配和独立运行的基本单位。

为使程序并发执行,且对并发执行的加以描述和控制,从而引入“进程”的概念。

进程特征:结构特征(进程控制块,PCB)、动态性(生命周期:创建、调度执行、撤销)、并发性(进程实体和其他进程实体并发执行)、独立性(独立运行、独立分配资源、独立接受调度)、异步性(进程实体按异步方式运行)。

进程(Process):每个独立的程序在计算机上的一次执行活动。例如运行中的QQ程序、运行的MP3播放器。每运行一个程序,就是启动一个进程。程序是静态的,而进程是动态的。

1、进程状态:就绪状态(Ready)、执行状态、阻塞状态

2、进程管理

进程控制:创建进程、终止进程

进程同步:对多个相关进程在执行次序上进行协调,使并发的进程能有效地共享资源和相互合作。

争夺临界资源会出现系统混乱,例如多个进程争用共享的变量、链表时,会导致数据处理出错。

经典进程同步问题:生产者-消费者问题

进程通信:进程间信息交换

进程间互斥和同步,交换的信息量比较少,被归结为低级通信。

高级通信:用户直接利用操作系统所提供的一组通信命令高效地传送大量数据的通信方式。OS隐藏了进程间通信的具体实现细节,或者说是通信过程对于用户来说是透明的,这样就大大减少了通信程序编制的复杂性。

高级通信机制:共享存储器系统、消息传递系统、管道通信

消息传递通信

直接通信方式:利用OS提供的发送命令,直接把消息发送给目标进程。

间接通信方式:需要共享的数据结构实体,暂存发送进程发送给目标进程的消息。

消息传递系统实现过程中需要考虑的若干问题

1)通信链路(发送进程和接受进程能进行通信,在两者之间建立一条链路。一种是直接显示建立连接;另一种是根据建立链路的请求,系统自动为之建立链路。)

通信链路:点-点连接通信链路、多点连接链路;单向通信链路、双向链路;无容量通信链路、有容量通信链路(缓冲区,暂存消息)。

2)消息格式(单机系统:发送进程和接受进程处于同一台机器,消息格式比较简单;计算机网络环境:消息格式复杂,消息头+消息正文)

3)进程同步方式(进程同步机制使各进程间能协调通信、发送进程、接收进程)

4)消息缓冲队列通信机制(数据结构:消息缓冲区;发送;接收)


线程(Thread):进程进一步细分为线程,为提供程序并发执行的程度。

线程:比进程更小的能独立运行的基本单位。

在OS中引入进程是为使多个程序并发执行,来提供系统资源利用率和系统吞吐量,那么在引入线程,则是为减少程序在并发执行时的系统开销,使OS具有更好的并发性。

进程是一个可拥有资源的独立单位,又是一个可独立调度分配的基本单位。考虑到若将进程的这两个属性分开,由OS来分开处理,使其“轻装上阵”,对于拥有资源的基本单位,而又不轻易进行切换,这样就形成了“线程”的初步思想。

线程与进程的比较

1)调度:线程基本不拥有资源,作为调度和分派的基本单位,这样线程便能轻装前进,从而显著提高系统的并发程度。同一进程中,线程间的切换不会引起进程的切换。

2)并发性:

3)拥有资源:

4)系统开销:

区别如下:

1)每个进程都有独立的代码和数据空间(进程上下文),进程间切换开销大。

2)同一进程内的多个线程共享相同的代码和数据空间,每个线程能独立运行(独立的运行栈和程序计算器),线程间切换开销较小。


线程的创建和启动

Java语言的JVM允许应用程序同时运行多个线程,线程是通过java.lang.Thread类来实现。

Thread类特性:1)每个线程都是通过某个特定Thread对象的run()方法来完成其操作的,经常把run()方法的主体称为线程体。

2)通过该Thread对象的start()方法来调用这个线程。也就是说,创建Thread类(或其子类)的一个实例,只是意味着该线程处于“新建”状态,其线程体中的代码并未执行。当调用了该线程实例的start()方法,该线程便是个可运行的线程了,直到操作系统为该线程分配了运行时间,则该线程就开始运行了。

创建线程的方式

1)定义实现java.lang.Runnable接口的类,Runnable接口中只有一个run()方法,用来定义线程运行体。

定义好类之后,需要将其实例作为参数传递给Thread的构造方法来创建一个新线程。

class MyRunner implements Runnable{
	public void run(){
		//要在线程中执行的代码
		for(int i = 0; i < 10; i++){
			System.out.println("MyRunner: " + i);
		}
	}
}

public class ThreadTest {
	public static void main(String[] args){
		Thread thread1 = new Thread(new MyRunner());
		thread1.start();
	}
}

2)将类定义为Thread的子类并重写run()方法。

class MyThread extends Thread{//继承Thread类,
	public void run(){
		//要在线程中执行的代码
	}
}

注:建议采用第一种方式,因为采用实现接口的方式可以避免单一继承带来的局限性,有利于代码的健壮性。

线程调度:让JVM对多个线程进行系统级的协调,避免多个线程争用有限的资源而导致系统死机或崩溃的状态。

线程同步:多个线程同时访问共享的数据时,必须对访问进行同步。

线程同步的方法:为了共享区域的安全可以通过关键字synchronized加以限定,保证数据的安全,synchronized主要应用于同步代码块和同步方法中。

1)同步方法:synchronized用于方法声明中,表示该方法为同步方法。

public synchronized boolean sell(){
		//同步售票方法
		///..........................
	}

2)同步代码块:把线程体中执行的方法为操作到共享数据的语句放在{}之间,然后用synchronized修饰这个代码块。这种方法只是同步了会操作到共享数据的代码,比整个同步方法更有效。

public boolean sell(){
		//同步代码块
		synchronized(this){
			///..........................
		}
	}

同步机制的主要实现方式是利用“对象锁”,即在某个时间点上,一个对象的锁只能被一个线程拥有。

在JDK1.5以后,java提供了一种显示加锁机制,即使用java.util.concurrent.locks.Lock接口提供的lock()方法获取锁,用unlock()方法释放锁。


同步线程和异步线程运行情况比较

集合类是编程过程中经常要用到的,java.util包中的集合类有的是线程同步(也叫线程安全)的,但大多数的集合类是线程不同步(也叫线程不安全)的。例如常用到的集合类HashSet、ArrayList、LinkedList、HashMap等都是线程不同步的。在编写多线程的程序时,如果多个线程都会操作到共享的集合类对象(成员变量),那么就必须自行实现同步以确保共享集合类对象在多线程下存取不会出错。


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值