这篇的主题本应该放在最初的几篇。讨论的是并发编程最基础的几个核心概念。可是这几个概念又牵扯到非常多的实际技术。比方Java内存模型。各种锁的实现,volatile的实现。原子变量等等,每个都可以展开写非常多,尤其是Java内存模型,网上已经可以有非常几篇不错的文章,临时不想反复造轮子。这里推荐几篇Jave内存模型的资料:

1. JSR-133 FAQ

2. JSR-133 Cookbook

3. Synchronization and Java Memory Model

4. 深入理解Java内存模型

我之前也写了一个Java内存模型的PPT: http://share.csdn.net/slides/7916

以下说说并发编程关注的几个核心概念。

关注一个并发问题,有3个主要的关注点:

1. 安全性。也就是正确性。指的是程序在并发情况下运行的结果和预期一致

2. 活跃性,比方死锁。活锁

3. 性能,降低上下文切换。降低内核调用。降低一致性流量等等

安全性问题是首要解决的问题。保证程序的线程安全。实际上就是对多线程的同步,而多线程的同步本质上就是多线程通信的问题。操作系统里面定义了几种进程通信的方式:

1. 管道 pipeline

2. 信号 signal

3. 消息队列 messsage queue

4. 共享内存 shared memory

5. 信号量 semaphore

6. Socket

Java里面进行多线程通信的主要方式就是共享内存的方式,共享内存基本的关注点有两个:可见性和有序性。加上复合操作的原子性。我们能够觉得Java的线程安全性问题主要关注点有3个

1. 可见性

2. 有序性

3. 原子性

Java内存模型JMM攻克了可见性和有序性的问题,而锁攻克了原子性的问题。

至于Java内存模型怎样解决可见性和有序性的问题,以后会说到,感兴趣的同学能够看看上面的资料。

可见性指的是一个线程对变量的写操作对其它线程兴许的读操作可见。因为现代CPU都有多级缓存,CPU的操作都是基于快速缓存的,而线程通信是基于内存的,这中间有一个Gap, 可见性的关键还是在对变量的写操作之后可以在某个时间点显示地写回到主内存,这样其它线程就能从主内存中看到最新的写的值。volatile,synchronized, 显式锁,原子变量这些同步手段都可以保证可见性。

可见性底层的实现是通过加内存屏障实现的:

1. 写变量后加写屏障。保证CPU写缓冲区的值强制刷新回主内存

2. 读变量之前加读屏障。使缓存失效,从而强制从主内存读取变量最新值

写volatile变量 = 进入锁

读volatile变量 = 释放锁

有序性指的是数据不相关的变量在并发的情况下。实际运行的结果和单线程的运行结果是一样的。不会由于重排序的问题导致结果不可预知。volatile, final, synchronized。显式锁都能够保证有序性。

有序性的语意有几层,

1. 最常见的就是保证多线程运行的串行顺序

2. 防止重排序引起的问题

3. 程序运行的先后顺序。比方JMM定义的一些Happens-before规则

 



重排序的问题是一个单独的主题。常见的重排序有3个层面:

1. 编译级别的重排序,比方编译器的优化

2. 指令级重排序,比方CPU指令运行的重排序

3. 内存系统的重排序,比方缓存和读写缓冲区导致的重排序





原子性是指某个(些)操作在语意上是原子的。比方读操作。写操作,CAS(compare and set)操作在机器指令级别是原子的,又比方一些复合操作在语义上也是原子的,如先检查后操作if(xxx == null){}

有个专有名词竞态条件来描写叙述原子性的问题。

竞态条件(racing condition)是指某个操作因为不同的运行时序而出现不同的结果,比方先检查后操作。

volatile变量仅仅保证了可见性,不保证原子性, 比方a++这样的操作在编译后实际是多条语句。比方先读a的值,再加1操作。再写操作。运行了3个原子操作,假设并发情况下,另外一个线程非常有可能读到了中间状态,从而导致程序语意上的不对。

所以a++实际是一个复合操作。

加锁能够保证复合语句的原子性。sychronized能够保证多条语句在synchronized块中语意上是原子的。

显式锁保证临界区的原子性。

原子变量也封装了对变量的原子操作。非堵塞容器也提供了原子操作的接口,比方putIfAbsent。


理解可见性,有序性。原子性是理解并发编程的一个重要基础

聊聊高并发(十九)理解并发编程的几种"性" -- 可见性,有序性,原子性的更多相关文章

  1. python学习笔记(十九)面向对象编程,类

    一.面向对象编程 面向对象,是一种程序设计思想. 编程范式:编程范式就是你按照什么方式去编程,去实现一个功能.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,两种最重要的编程范式分 ...

  2. 转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

      Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.coc ...

  3. JAVA学习第五十九课 — 网络编程概述

    网络模型 OSI(Open System Interconnection)开放系统互连:參考模型 TCP/IP 网络通讯要素 IP地址 port号 传输协议 网络參考模型 七层OSI模型的基本概念要了 ...

  4. 五十九、linux 编程—— I/O 多路复用 fcntl

    59.1 介绍 前面介绍的函数如,recv.send.read 和 write 等函数都是阻塞性函数,若资源没有准备好,则调用该函数的进程将进入阻塞状态.我们可以使用 I/O 多路复用来解决此问题(即 ...

  5. 【Java并发核心九】并发集合框架

    1.List接口:ArrayList 和 Vector ArrayList不是线程安全的,Vector是线程安全的,Vector有一个子类,可实现后进先出(LIFO)的对象堆栈(LinkedList ...

  6. 流畅的python第十九章元编程学习记录

    在 Python 中,数据的属性和处理数据的方法统称属性(attribute).其实,方法只是可调用的属性.除了这二者之外,我们还可以创建特性(property),在不改变类接口的前提下,使用存取方法 ...

  7. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  8. 聊聊高并发(二十五)解析java.util.concurrent各个组件(七) 理解Semaphore

    前几篇分析了一下AQS的原理和实现.这篇拿Semaphore信号量做样例看看AQS实际是怎样使用的. Semaphore表示了一种能够同一时候有多个线程进入临界区的同步器,它维护了一个状态表示可用的票 ...

  9. 聊聊高并发(二十九)解析java.util.concurrent各个组件(十一) 再看看ReentrantReadWriteLock可重入读-写锁

    上一篇聊聊高并发(二十八)解析java.util.concurrent各个组件(十) 理解ReentrantReadWriteLock可重入读-写锁 讲了可重入读写锁的基本情况和基本的方法,显示了怎样 ...

随机推荐

  1. 基于深度学习的病毒检测技术无需沙箱环境,直接将样本文件转换为二维图片,进而应用改造后的卷积神经网络 Inception V4 进行训练和检测

    话题 3: 基于深度学习的二进制恶意样本检测 分享主题:全球正在经历一场由科技驱动的数字化转型,传统技术已经不能适应病毒数量飞速增长的发展态势.而基于沙箱的检测方案无法满足 APT 攻击的检测需求,也 ...

  2. 6. Intellij Idea 2017创建web项目及tomcat部署实战

    转自:https://www.cnblogs.com/shindo/p/7272646.html 相关软件:Intellij Idea2017.jdk16.tomcat7 Intellij Idea直 ...

  3. django 笔记11 装饰器

    在views.py创建 一般用来cookies的装饰器 def auth(func): def inner(request, *args, **kwargs): v = request.COOKIES ...

  4. json数据字典,以及数据在下拉框中显示

    建立person_vocation.json数据字典文件,内容: [ {"id":1,"disabled":false,"selected" ...

  5. Linux和Windows系统的远程桌面访问知识(转载)

    为新手讲解Linux和Windows系统的远程桌面访问知识   很多新手都是使用Linux和Windows双系统的,它们之间的远程桌面访问是如何连接的,我们就为新手讲解Linux和Windows系统的 ...

  6. [JLOI2011]飞行路线 分层图最短路

    题目描述: Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在nn个城市设有业务,设这些城市分别标记为0到n-1,一共有m种航线,每种航线连接两个城市,并且航线有一 ...

  7. Kubernetes1.5 集成Heapster

    Kubernetes1.5 集成Heapster Heapster是kubernetes集群监控工具.在1.2的时候,kubernetes的监控需要在node节点上运行cAdvisor作为agent收 ...

  8. ES6学习笔记(十六)async函数

    1.含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便. async 函数是什么?一句话,它就是 Generator 函数的语法糖,号称异步的终极解决方案. 前文有一个 Gen ...

  9. cookie 实现记住用户名演示 通过代码迅速理解cookie

    // 登录页 可直接 tomcat部署 测试 1 package com.itheima.login; import java.io.IOException; import java.io.Print ...

  10. Linux权限管理(用户、组、文件管理)

    一. Linux上的文件管理类命令都有哪些,其常用的使用方法及其相关示例演示. 1. 文件查看类命令cat,tac, head, tail, more, less, ls ,file: -ls : l ...