一. java多线程编程基本概念--------基本概念

  java多线程可以说是java基础中相对较难的部分,尤其是对于小白,次一系列文章的将会对多线程编程及其原理进行介绍,希望对正在多线程中碰壁的小伙伴有所帮助。

  (一)进程、线程和任务

  进程可以认为是程序执行的一个实例,是程序向操作系统申请资源的基本单位,每个进程都拥有自己独立的地址空间。

  线程是操作系统能够进行运算调度的最小单元,它被包含在进程之中,一个进程可以有多个线程。同一个进程中的多个线程共享这个进程的资源。

  每个线程完成的计算被称为任务。

   (二)串行、并发和并行

  串行:按照顺序完成多个任务。

  并发:在一段时间内以交替的方式完成多个任务。

  并行:以齐头并进的方式完成多个任务。

  并发往往是带着部分串行的并发,并发的极致就是串行。一个处理器就可以实现并发,但并行需要多个处理器在同一个时刻各自运行一个线程来实现。

  多线程编程的实质就是将任务的处理方式由串行改为并发。

  (三)多线程编程的优缺点

  • 优点

  提高系统的吞吐率;调高响应性;充分利用多核处理器;最小化对资源的使用(相对于多进程)

  • 缺点

  可能会造成线程安全问题、线程活性问题、引起上下文切换

  (四)竟态

  竟态是指一个计算结果的正确性和时间有关的现象。竟态往往伴随着读脏数据问题(线程读到的是一个过时的数据)、丢失更新(一个线程对数据所做的更新没有体现到后续其他线程对该数据的读取上)。

  竟态通常是在多个线程在没有采取任何控制措施的情况下并发更新、读取同一个共享变量。竟态的两种模式为:read-modify-write(读-改-写)和check-then-act(检测而后行动)。

  (五)线程安全问题

   线程安全问题概括起来变现为3个方面:原子性、可见性和有序性。

  1. 原子性

  原子性是指访问某个共享变量的操作从执行线程以外的其他线程来看,该线程要么执行结束,要么尚未发生,即其他线程不会看到该操作的中间结果。java语言中,任何数据类型的读操作都具有原子性,除了long和double类型的基本数据类型和引用数据类型的写操作都具有原子性。

  Java中有两种方式实现原子性:使用锁、CAS

  2. 可见性

  可见性用于描述一个行程对共享变量的更新对于另外一个线程而言是否可见的问题。可见性的保障是通过使更新共享变量的处理器执行冲刷处理器缓存,使读取共享变量的处理器执行刷新处理器缓存。

  父线程在启动子线程之前对共享变量的更新对于子线程来说是可见的,之后对于共享变量的更新对于子线称来说没有保障的。

  3. 有序性

  有序性用来描述一个线程的内存访问操作在另外一个线程看来是否有序的问题。

  重排序可以分为一下三种:

  1)编译器优化的重排序。编译器在保证貌似串行语义的情况下,可以重新安排语句的执行顺序。

  2)指令级并行重排序:如果不存在数据依赖性,处理器可以语句对应机器指令的执行顺序。

  3)内存系统重排序。由于处理器使用缓存和读写缓冲区,使得加载和存储操作看上去是乱序的。

  (六)java内存模型和happens-before

  Java内存模型使用happens-before关系来保证可见性和有序性。

  1. java内存模型

  java内存模型(即Java Memory Model,简称JMM)本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。由于JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝,前面说过,工作内存是每个线程的私有数据区域,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成,其简要访问过程如下图

  

  2. happens-before

  happens-before有两层含义:

  1)如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,第一个操作的执行顺序排在第二个操作之前。(这条是JMM对程序员的承诺)

  2)两个操作之间存在happens-before关系,并不意味着java平台的具体实现必须要按照happens-before关系指定的顺序来执行,只要保证重排序之后的结果与按happens-before关系一致即可(这条JMM对编译器和处理器重排序的约束)。

  貌似串行语义(as-if-serial)保证单线程内程序执行结果不改变,happens-before关系保证正确同步的多线程程序执行结果不改变。

  具体规则:

  • 程序顺序规则:同一个线程中的每个操作happens-before该线程中的任意后续操作。
  • 内部锁规则:内部锁的释放happens-before后续每一个对该锁的申请
  • volatile规则:对于一个volatile域的写happens-before后续每一个针对该变量的读操作
  • 传递性:如果A happens-before B,B happens-before C,那么A happens-before C
  • start()规则:如果线程执行操作B.start(),那么A线程中的B.start()操作happens-before B线程中的任意操作
  • join()规则:如果A线程执行B.start()操作并成功返回,那么b线程中的任意操作happens-before A线程执行完B.start()返回后的任意操作。
  • 程序中断规则:对线程iterrupted()的调用先行于被中断线程检测到中断事件的发生。
  • 对象finalize规则:一个对象的初始化完成先行于它的finalize()方法的开始。

  (七) 阻塞与非阻塞

  阻塞和非阻塞用来形同多线程间的相互影响,一个线程占用了临界区资源,其他线程需要这个资源进行等待该资源的释放,会导致等待线程的挂起,这种情况就是阻塞,而非阻塞恰好相反,他强调没有一个线程可以阻塞其他线程,所有线程都会尝试着往前运行。

java多线程编程01---------基本概念的更多相关文章

  1. Java多线程编程总结一:多线程基本概念

    Java多线程编程总结一 – 初识多线程 进程.多进程.线程.多线程的概念 进程(process):CPU的执行路径.通俗的说就是系统中正在运行的程序.比如我们打开了浏览器.QQ等等,这些程序一旦被打 ...

  2. Java多线程编程详解

    转自:http://programming.iteye.com/blog/158568 线程的同步 由于同一进程的多个线程共享同一片存储空间,在带来方便的同时,也带来了访问冲突这个严重的问题.Ja ...

  3. Java多线程编程总结(精华)

    Java多线程编程总结 2007-05-17 11:21:59 标签:多线程 java 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http ...

  4. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  5. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  6. Java多线程编程实战读书笔记(一)

    多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.

  7. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

  8. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  9. Java - 32 Java 多线程编程

    Java 多线程编程 Java给多线程编程提供了内置的支持.一个多线程程序包含两个或多个能并发运行的部分.程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径. 多线程是多任务的一种特别 ...

随机推荐

  1. 推荐一个高大上的网易云音乐命令行播放工具:musicbox

    网易云音乐上有很多适合程序猿的歌单,但是今天文章介绍的不是这些适合程序员工作时听的歌,而是一个用Python开发的开源播放器,专门适用于网易云音乐的播放.这个播放器的名称为MusicBox, 特色是用 ...

  2. Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL

    一.IPC inter process communication  进程间通讯 二.AIDL android  interface  defination  language  安卓接口定义语言 满 ...

  3. exit - 使程序正常中止

    SYNOPSIS 总览 #include <stdlib.h> void exit(int status); DESCRIPTION 描述 函数 exit() 使得程序正常中止,statu ...

  4. 1.1 Qt入门

    学习Qt的前提是学好C++. 我刚入门Qt,打算趁着暑假2个月时间来学习<C++ GUI Qt 4>这本书. 现在有Qt4和Qt5,似乎很多公司都还是在使用Qt4,所以我也就选择了学习Qt ...

  5. 条款34:区分接口继承和实现继承(Different between inheritance of interface and inheritance of implemenation)

    NOTE: 1.接口继承和实现继承不同.在public继承之下,derived classes总是继承base class的接口. 2.pure virtual 函数只具体指定接口继承及缺省实现继承. ...

  6. git 项目相关

    工具篇:Sourcetree 和 Git Bash Sourcetree Git一款非常好用的可视化工具,方便管理项目.下载地址 https://www.sourcetreeapp.com/ Git ...

  7. SSM调用数据库存储过程

    ServiceImpl中: Map<String,Object> map=new HashMap<String,Object>(); map.put("bid&quo ...

  8. 对于单片机工程.h头文件的管理

    最近工程管理过于混乱,学习了一些工程头文件管理的方法,现在做一个记录,也分享给大家. 目前有两种管理文件的方式: 1.每一个功能模块对应一个文件夹,里面包含一个.c和一个.h文件如下图所示 这样做的好 ...

  9. npm 的作用

    接触 npm 也有一个多月的时间了,一直只是将他作为当着 webstorm + node.js 环境中的一个插件来用(甚至说把她当着命令来用).毕竟大部分的时间,他是输入的命令行中的一部分(别笑,小新 ...

  10. ASP.NET Core on K8S学习初探(1)K8S单节点环境搭建

    当近期的一个App上线后,发现目前的docker实例(应用服务BFF+中台服务+工具服务)已经很多了,而我司目前没有专业的运维人员,发现运维的成本逐渐开始上来,所以容器编排也就需要提上议程.因此我决定 ...