高并发:
cpu -- 缓存 -- 内存
资源利用率
公平性
便利性
 
生活举例 --- 串行任务中的异步性:我在烧水的时候看书 --- 平衡点
 
安全性问题 --- 产生竞态条件
共享数据 --- 共享相同的内存地址,并且并行执行
不可破坏 --- 永远不要发生最糟糕的事情
活跃性问题 --- 某个正确的事情最终会发生
某个操作无法执行下去
 
性能问题 --- 频繁的上下文切换,CPU花更多的时间在线程调度上

编写安全的多线程代码,核心在于对状态访问操作进行管理
共享(Shared):可被多线程访问
可变(Mutable) :在对象生命周期内可发生变化
对象状态,存储在状态变量(实例或静态域)中的数据,对象状态还可能依赖其他对象域
 
在程序访问对象的角度看这个问题
一个对象是否线程安全,取决于它是否被多线程访问。使用同步机制保证线程安全
 
需使用同步机制的情况:
当多线程访问一个状态变量,并且其中有一个线程进行写入操作时,必须采用同步机制协同线程对变量的访问
Java的同步机制
synchronized --- 重量级,独占加锁。
volatile类型变量
显式锁
原子变量
 
当多线程访问状态变量时,没有采取适合的同步机制则:
不在线程之间共享该变量
将状态变量改为不可变的变量
在访问状态变量时使用同步
 
线程安全类
线程安全程序
线程安全的程序是否完全由线程安全类构成?
完全由线程安全类构成的程序不一定线程安全。线程安全类中也可以包含非线程安全的类

线程安全性
多线程下的正确性 --- 当多线程下访问某个类,这个类始终都能保证正确的行为
单线程下的正确性 --- 所见即所得
 
无状态对象一定是线程安全的
 
原子性问题,修改变量时,实际可能并不是原子操作(读取---修改---写入),多线程下可能由于时序问题产生的数据不一致-----竞态条件 --- 安全性问题
先检查后执行 --- 通过一个可能失效的结果决定下一步动作
e.g A去地点Q的星巴克与B会面,到达Q之后发现有两家星巴克分别叫S1,S2.在S1没有看到B,然后去到S2也没有看到B,B迟到,B在A离开S1后到了S1,B到达S2但是B去S1找A.
 
延迟加载的竞态条件

竞态条件和数据竞争(Data Race)
数据竞争:在访问共享变量的非final类型的域时没有采用同步进行协同,那么就会出现数据竞争。当一个线程写入一个变量,另一个线程读取这个变量,或者读取一个之前由另一个线程写入的变量时,
并且这两个线程直接没有使用同步,就会出现数据竞争。不是所有竞态条件都是数据竞争,同样并非所有数据竞争都是竞态条件,但两者都会导致并发程序失败。
 
如何保证原子性:
复合操作保证原子性
原子操作:对于访问同一个状态的所有操作(包括该操作本身)来说,这个操作是一个以原子方式执行的操作
 
待解决的小功能 --- 实现一个因式分解 (缓存上一次计算的结果)
 
保存状态一致(一致性),需要带单个原子操作中更新所有相关的状态变量
 
内置锁(监视器锁)--- 是一个互斥锁,即A尝试获取由B线程持有的锁时,A会阻塞,且等到B释放锁后A才能重新获得锁
synchronized(lock){
}
作为所的对象引用
这个锁保护的代码块
 
重入
内置锁是可重入的,当一个线程试图获取它已经持有的锁时,这个请求会成功。其他线程尝试获取会阻塞unt 。获取锁的粒度是线程,而不是调用。
countNum = 0 --没有线程持有锁
countNum = 1 -- 当前有一个线程持有锁
重入CountNum++
在释放时,会依次递减 --- 直到为0
 
 
用锁保护状态
对于可能被多个线程同时访问的可变状态变量,在访问它时,都需要持有同一把锁 ---- 这个变量由这个所保护
对于每个包含多个变量的不变性条件,其中所涉及到的变量都需要同一把锁来保护
synchronized可保证单个操作的原子性,但是保证不了符和操作的原子性
当执行较长时间计算,可能无法快速完成操作时,一定不要持有锁

 

Java并发编程杂记(1)的更多相关文章

  1. Java并发编程杂记(2)

    对象共享 synchronized 设定原子性确定临界区 + 内存可见性 要解决如下问题 防止一个线程在使用对象状态而另一个线程在修改对象状态:且当一个线程修改了对象状态后,对其他线程可见.   可见 ...

  2. 【Java并发编程实战】----- AQS(四):CLH同步队列

    在[Java并发编程实战]-–"J.U.C":CLH队列锁提过,AQS里面的CLH队列是CLH同步锁的一种变形.其主要从两方面进行了改造:节点的结构与节点等待机制.在结构上引入了头 ...

  3. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  4. 【Java并发编程实战】----- AQS(二):获取锁、释放锁

    上篇博客稍微介绍了一下AQS,下面我们来关注下AQS的所获取和锁释放. AQS锁获取 AQS包含如下几个方法: acquire(int arg):以独占模式获取对象,忽略中断. acquireInte ...

  5. 【Java并发编程实战】-----“J.U.C”:CLH队列锁

    在前面介绍的几篇博客中总是提到CLH队列,在AQS中CLH队列是维护一组线程的严格按照FIFO的队列.他能够确保无饥饿,严格的先来先服务的公平性.下图是CLH队列节点的示意图: 在CLH队列的节点QN ...

  6. 【Java并发编程实战】-----“J.U.C”:CountDownlatch

    上篇博文([Java并发编程实战]-----"J.U.C":CyclicBarrier)LZ介绍了CyclicBarrier.CyclicBarrier所描述的是"允许一 ...

  7. 【Java并发编程实战】-----“J.U.C”:CyclicBarrier

    在上篇博客([Java并发编程实战]-----"J.U.C":Semaphore)中,LZ介绍了Semaphore,下面LZ介绍CyclicBarrier.在JDK API中是这么 ...

  8. 【Java并发编程实战】-----“J.U.C”:ReentrantReadWriteLock

    ReentrantLock实现了标准的互斥操作,也就是说在某一时刻只有有一个线程持有锁.ReentrantLock采用这种独占的保守锁直接,在一定程度上减低了吞吐量.在这种情况下任何的"读/ ...

  9. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

随机推荐

  1. Windows下搭建远程Linux主机的图形化本地开发环境

    在实际开发中,项目的类生产.生产环境一般都是选择Linux为服务器进行部署. 相应的,我们的开发最好也在Linux环境下进行,否则容易引发其他的问题,比如不同环境下功能不一致.库依赖差异等. 但是Li ...

  2. 理解Spark SQL(二)—— SQLContext和HiveContext

    使用Spark SQL,除了使用之前介绍的方法,实际上还可以使用SQLContext或者HiveContext通过编程的方式实现.前者支持SQL语法解析器(SQL-92语法),后者支持SQL语法解析器 ...

  3. cn_windows虚拟机配置

    1.打开“VMware”,点击“主页”,点“创建新的虚拟机”: 2.会弹出一个“新建虚拟机向导”,类型选择“典型”,点击“下一步”: 3.选择“稍后安装操作系统”,点击“下一步”: 4.选择“Micr ...

  4. python:模块0

    一.模块是更高级的封装: 容器:数据的封装 函数:语句的封装 类   :方法和属性的封装 模块:模块就是程序,即每个.py文件 二.引入 import 模块名 from 模块名 import xx(函 ...

  5. 图文详解基于角色的权限控制模型RBAC

    我们开发一个系统,必然面临权限控制的问题,即不同的用户具有不同的访问.操作.数据权限.形成理论的权限控制模型有:自主访问控制(DAC: Discretionary Access Control).强制 ...

  6. C# - VS2019 WinFrm应用程序开发报表 - ReportViewer控件初涉

    前言 简单报表我们可以通过label.textBox和PrintDialog来实现,但是一般在实际生产过程中,用户的报表需求一般都是比较复杂的. 本篇主要记录对于传统中国式复杂报表的处理方法和解决思路 ...

  7. Python装饰器的使用

    对于python编程人员,装饰器的使用肯定是必不可少的. 装饰器分为系统定义装饰器和自定义装饰器:系统定义装饰器:@classmethod:类方法装饰器  @staticmethod:   静态方法装 ...

  8. PHP变量的初始化以及赋值方式介绍

    什么是变量 变量通俗的来说是一种容器.根据变量类型不同,容器的大小不一样,自然能存放的数据大小也不相同.在变量中存放的数据,我们称之为变量值. PHP 中的变量用一个美元符号后面跟变量名来表示.变量名 ...

  9. 【笔记】总结Springboot和Vue前后端分离的跨域问题

    跨域一直是个很玄学的问题,SSM的时候又得前后端一起配置,sb的时候又不用. 前端 axios普通get请求 submitForm() { var v=this; this.$axios({ meth ...

  10. Oracle 分区表管理之组合分区(分区索引失效与性能比较)

    整体结构如下: Oracle  分区表管理之组合分区(分区索引失效与性能比较) 虽然老早就使用了分区表,终于有时间写有关分区表的内容:不是所有的场景数据量变大需要用到分区表,一般单表数据超过2g可以考 ...