【Java并发编程】并发、线程与等待通知机制

1 理论

1.2 线程

线程优缺点

(1)优点

  • 加快响应用户时间;
  • 使代码模块化、异步化、简单化;
  • 充分利用多核cpu的计算能力,提高系统的并发和性能;

(2)缺点

  • 内存泄漏;

ThreadLocal使用不当会导致内存泄漏,具体参考本文ThreadLocal知识点;

  • 线程安全问题;

线程不安全:servlet单实例多线程、controller,可以通过ThreadLocal处理多线程安全问题;
线程安全:struts,漏洞多已被淘汰;

  • 线程死锁问题;

线程相互引用,ABA问题导致死锁;

  • 线程上下文切换降低性能;

用户态切换到内核态需要消耗CPU性能,线程越多需要的系统资源越多;

程序/进程/线程

(1)程序
应用程序,比如APP对应的exe文件,由指令和数据组成;
(2)进程
站在操作系统的角度,进程是程序运行资源分配的基本单位;
进程间通讯方式:

  1. 管道,分为匿名管道(pipe)及命名管道(named pipe):匿名管道可用于具有亲缘关系的父子进程间的通信,命名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
  2. 信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
  3. 消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
  4. 共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
  5. 信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间的同步和互斥手段
  6. 套接字(socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。同一机器中的进程还可以使用Unix domain socket(比如同一机器中 MySQL 中的控制台 mysql shell 和 MySQL 服务程序的连接),这种方式不需要经过网络协议栈,不需要打包拆包、计算校验
    和、维护序号和应答等,比纯粹基于网络的进程间通信肯定效率更高。

(3)线程
一个进程可包含多个线程,是CPU处理器任务调度和执行的基本单位;
服务器可以有多个cpu,一个cpu可以有多个核(超线程基础将一个物理核可以拆分成多个逻辑处理器),一个核处理一个线程,一个线程只能同时运行在一个cpu核心上;
在 Java 中提供了 Runtime.getRuntime().availableProcessors(),可以让我们获取当前的 CPU 核心数,注意这个核心数指的是逻辑处理器数。获得当前的 CPU 核心数在并发编程中很重要,并发编程下的性能优化往往和 CPU 核心数密切相关。

线程上下文

(1)概念
多线程编程中,一般线程个数大于cpu的核数,而一个cpu核同一时间只能处理一个线程,为了能使所有的线程都能被执行(呈现出并行处理的效果),cpu采用时间片的形式执行多个线程。当一个线程的时间片用完,保存运行状态后,cpu切换到另一个线程执行,一个线程从执行到状态保存的过程,称之为线程上下文切换
上下文是 CPU 寄存器和程序计数器在任何时间点的内容;
(2)线程上下文切换包括

  • 线程切换,同一进程中的两个线程之间的切换
  • 进程切换,两个进程之间的切换
  • 模式切换,在给定线程中,用户模式和内核模式的切换
  • 地址空间切换,将虚拟内存切换到物理内存

(3)上下文切换可以更详细地描述为内核(即操作系统的核心)对 CPU 上的进程(包括线程)执行以下活动:

  1. 暂停一个进程的处理,并将该进程的 CPU 状态(即上下文)存储在内存中的某个地方;
  2. 从内存中获取下一个进程的上下文,并在 CPU 的寄存器中恢复它;
  3. 返回到程序计数器指示的位置(即返回到进程被中断的代码行)以恢复进程;

(4)说明
线程上下文操作通常是计算密集型的,需要消耗大量的处理器时间,可能是操作系统中耗时最大的操作;
就 CPU 时间而言,一次上下文切换大概需要 5000~20000 个时钟周期,相对一个简单指令几个乃至十几个左右的执行时钟周期,可以看出这个成本的巨大;

并行和并发

并发 Concurrent
指应用能够交替执行不同的任务,比如单 CPU 核心下执行多线程并非是同时执行多个任务,如果你开两个线程执行,就是在你几乎不可能察觉到的速度不断去切换这两个任务,已达到“同时执行效果”,其实并不是的,只是计算机的速度太快,我们无法察觉到而已;
一般说的是单位时间内的并发,离开单位时间谈并发没有意义;
并行 Parallel
指应用能够同时执行不同的任务,例:吃饭的时候可以边吃饭边打电话,这两件事情可以同时执行;
两者区别:
一个是交替执行,一个是同时执行,如下图所示:
【Java并发编程】并发、线程与等待通知机制_第1张图片

你可能感兴趣的:(#,Java基础,并发编程,thread)