高并发:
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. hdu 4337 King Arthur's Knights (Hamilton)

    King Arthur's KnightsTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  2. openresty(nginx)中使用lua脚本获取请求IP地址的代码

    人狠话不多,直接上代码:------------------------------------------------------------------------------------- lo ...

  3. PostGIS 查看表属性(字段、类型、是否为空)

     SELECT                a.attnum,                a.attname AS field,                t.typname AS type ...

  4. C语言之路

    C 简介 C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的.C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现. 在 1978 ...

  5. Java入门系列之集合HashMap源码分析(十四)

    前言 我们知道在Java 8中对于HashMap引入了红黑树从而提高操作性能,由于在上一节我们已经通过图解方式分析了红黑树原理,所以在接下来我们将更多精力投入到解析原理而不是算法本身,HashMap在 ...

  6. day 22 面向对象的基础

    面向对象: 1.简述编写和执行类中的方法的流程 class Foo: #类的编写 def func(): print("我爱你") obj = Foo() #类的调用和执行 obj ...

  7. Python3学习-基础

    1.直接运行.py文件 在Windows上是不行的,但是在Mac和Linux上是可以的,方法是在.py文件的第一行加上一个特殊的注释: #!/usr/bin/env python3 print('he ...

  8. 本地存储常用方式 localStorage, sessionStorage,cookie 的区别 和 服务器存储session

    本地存储:把一些信息存储到客户端本地(主要目的有很多,其中有一个就是实现多页面之间的信息共享)       1. 离线缓存(xxx.manifest)  H5处理离线缓存还是存在一些硬伤的,所以真实项 ...

  9. CMSdede后台登陆界面设计

    1 在这里我就公布 css 和jq  也就是dede文件下templets的login.htm页面:代码如下      $(function () {             $(".tex ...

  10. 《Windows内核安全与驱动开发》 7.1&7.2&7.3 串口的过滤

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 7.1&7.2&7.3 串口的过滤 一.设备绑定的内核API ...