Java并发编程阅读笔记(一)

一、并发背景

之前的计算机是非常死板的,从头到尾就是一个程序,它这个程序只能安心做一件事,而且计算机中所有的资源都可以供他使用。这种程序造成的弊端就是浪费资源,因为它只能运行一个程序。

为了解决这种死板的问题,操作系统出现了。在操作系统的作用下,计算机可以同时执行多个进程,而且这些进程都是互相独立执行的,都可以获得计算机中的资源(如内存、文件句柄、安全证书等)。在一些情况下,进程之间可以通过一些通信机制进行数据交换,例如这些机制:

套接字 Socket、信号处理器、共享内存、文件等

二、操作系统出现(也就是进程的出现)的主要原因有3个:

(1)资源利用率

一些情况下,程序必须等待其他程序执行完之后才能执行,在这个漫长 的 等待 过程中,程序是无法执行其他工作,这样就会 对计算机的资源造成一定的浪费。如果在等待的同时可以运行其他程序,那么 资源的利用率就 提高了。

(2)公平性

不同的用户和程序对于计算机上的资源有相同的使用权。一种高效的运行方式是通过 “时间分片” 等待方式使用户和程序共享计算机资源。

(3)便利性

按照我们的惯性思维来说,计算多个任务时,应该编写多个程序,每个程序执行一个任务并在必要时互相通信,这比只编写一个程序来计算任务更容易实现。

三、线程出现的背景:

促使进程出现的原因(资源利用率、公平性、以及便利性等)也促使了线程的出现。线程允许在同一个进程中同时存在多个程序控制流。线程共享进程范围内的资源(如内存句柄,文件句柄等,每个线程都有各自的程序计数器、栈以及局部变量))。

其实线程也是轻量级进程,在大多数操作系统中,都是以线程为基本的调度单位,而不是进程。如果没有明确的协同机制,那么线程都将彼此独立执行。因为同一个进程中的线程共享进程 的内存地址空间,所以这些线程都能访问相同变量并且在同一个堆上分配对象,这就需要实现一种比进程间共享数据跟细微的 数据共享机制。如果没有明确的同步机制来协同对共享数据的访问,那么当一个线程正在使用某个变量时,另一个线程可能同时访问这个变量,将会导致不可预测的结果。

四、线程的优势:

如果线程使用得当,那么线程可以有效 降低程序开发和 维护的成本,同时提升复杂应用程序的性能。线程可以将大部分的异步工作流转换成 串行工作流。从而更好的模拟人类的工作方式和交互方式。线程还可以简化JVM的实现,垃圾收集器通常在一个或多个专门 的线程。

1.发挥多处理器的强大能力

2.异步事件的简化处理

服务器应用程序在接收多个客户端的套接字连接请求时,如果为每个连接都分配各自的线程并且使用同步 I/O,那么就很容易开发这种程序。

如果某个应用程序对套接字执行读操作而此时还没有数据到来,那么这个读操作将会阻塞,直到有数据到达它才会通行。在单线程应用程序中,这不仅意味着在处理请求的过程中将停顿,而且还意味着在这个线程阻塞期间,对所有请求的处理都将停顿。为了避免这个问题,单线程服务器应用程序必须使用非阻塞 I/O(也就是NIO),这种I/O的复杂性要远远高于同步 I/O,并且很容易出错。如果每个请求都拥有自己的处理线程,那么在处理 某个请求时发生的阻塞将不会影响其他请求的处理。

在早期操作系统中,通常会将进程中可创建的线程数量限制在一个较低的阈值内,大约在数百个左右。因此,操作系统提供了一些高效的方法来实现多路I/O,例如Unix的select和poll等系统调用,要调用这些方法,Java类库需要获得一组实现非阻塞 I/O的包(java.nio)。然而,在现代操作系统中,线程数量已得到极大的提升,这使得在某些平台上,即使有更多的客户端,为每个客户端分配一个线程也是可行的。

3.响应灵敏的用户界面

传统的GUI应用程序通常都是单线程,如果主事件循环中调用的代码需要很长的的时间才能执行完成,那么用户界面就会”冻结“,直到代码执行完成。造成此现象的原因就是因为只有当执行控制权返回到主事件循环后,才能处理后续的用户界面事件

五、线程的风险

1.线程安全性问题

线程在没有充足同步的情况下,多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果。也就是多个线程之间的交替操作将会导致不可预料的结果。

1.1竞态条件:

在多线程环境下,由于多个线程要共享相同的内存地址空间,并且是并发运行,因此他们可能会访问其他线程正在使用的变量。线程会由于无法预料的数据变化而发生错误。因此要想使多线程程序的行为可以预测,必须对共享变量的访问操作进行 “协同”,也就是所谓的线程同步,这样才不会在线程之间发生彼此干扰。

2.活跃性问题

“安全性”的含义: “永远不发生糟糕的事情”;

“活跃性”的含义:“某件正确的事情最终会发生”。也就是当谋而操作无法继续执行下去时,就会发生活跃性问题。在串行程序汇总,活跃性问题的形式之一就是无意中造成的无限循环,从而导致循环之后的程序无法得到执行。

在多线程环境下,如果线程A在等待线程B释放其持有的资源,而线程B永远都不释放这些资源,那么A就会一直等待下去。

3.多线程性能问题

与活跃性问题密切相关的是性能问题。活跃性意味着某件正确的事情最终会发生,但却不够好,我们都希望正确的事情快点发生。

posted @ 2020-01-19 16:24  Yuxy_main  阅读(119)  评论(0编辑  收藏  举报