Java并发编程(十一)多线程并发编程

逆流者 2021年02月21日 36次浏览

此文为读书笔记,欢迎评论,谈论问题,共同进步!


什么是多线程并发编程

先区分下并发和并行:

  • 并发是指同一个时间段内多个任务同时都在执行,并且都没有执行结束;
  • 并行是说在单位时间内多个任务同时在执行;
  • 并发任务强调在一个时间段内同时执行,而一个时间段由多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行。

在单CPU的时代多个任务都是并发执行的,这是因为单个 CPU同时只能执行一个任务。在单 CPU时代多任务是共享一个CPU的,当一个任务占用 CPU运行时,其他任务就会被挂起,当占用CPU的任务时间片用完后,会把CPU让给其他任务来使用,所以在单CPU时代多线程编程是没有太大意义的,并且线程间频繁的上下文切换还会带来额外开销。

单个 CPU 上运行两个线程,线程A和线程B是轮流使用CPU进行任务处理的,也就是在某个时间内单个CPU只执行一个线程上面的任务。当线程A的时间片用完后会进行线程上下文切换,也就是保存当前线程A的执行上下文,然后切换到线程 B来占用 CPU 运行任务。

单个 CPU 线程执行图:

单个 CPU 上运行两个线程
双 CPU 配置:
在这里插入图片描述
正常我们的电脑都是多核多线程的,比如四核八线程,线程个数是多于cpu个数的,所以一般都叫多线程并发编程,而不是多线程并行编程。

为什么要进行多线程并发编程

多核CPU时代的到来打破了单核CPU对多线程效能的限制。多个CPU意味着每个线程可以使用自己的CPU运行,这减少了线程上下文切换的开销。

Java 中的线程安全问题

共享资源:是说该资源被多个线程所持有或者说多个线程都可以去访问该资源。

线程安全问题:是指当多个线程同时读写一个共享资源并且没有任何同步措施时,导致出现脏数据或者其他不可预见的结果的问题。

看张图,我们具体描述下:

在这里插入图片描述

比如有两个线程在访问共享变量,线程A和线程B
共享变量1为一个count值,初始值为0。

t1t2t3t4
线程A从内存中读取共享变量1到本地递增本线程共享变量1的值写回主内存
线程B 从内存中读取共享变量1的值到本地递增本线程共享变量1的值写回主内存

线程A 在t1时刻从内存读取值为0,t2时刻递增后为1,t3时刻把count值写入了内存

线程B 在t2读取内存值为0,t3时刻递增后为1,t4时刻把count值写入内存

正常两个线程对count都做了递增操作,那count为2才对呀,但事实是count值为1,线程B不知道线程A已经把count递增了,所以存在线程安全问题。

请看下篇文章:Java 中共享变量的内存可见性问题