Java高并发与JVM

1、Java高并发

1.1CPU cache

所有的计算都是由CPU进行操作的,然而CPU的读写速度远远大于Main Memory的读写速度,故在CPU中添加了高速缓存,缓存分为3级,每一级都是都是由指令数据构成。

1.2Java内存模型-JMM

Java的高并采用的是共享内存模型,即同一个内存中变量可被多个线程同时使用。但是引入了一个新的问题,缓存不一致问题,当多个线程同时修改一个变量时,会有线程安全问题。

1.3并发编程中的三个特性 *

原子性
一次操作要么成功要么失败
可见性
多线程操作一个变量时,一个线程修改了值,要对另外线程可见
有序性
你的代码在运行过程中的先后执行顺序 Java编译器运行有优化
并发编程当满足此三个条件时才能保证线程安全。

volatile
– 不保证原子性 ,如volatile修饰的变量i,并发进行i++时,也会发生线程安全问题
– 保证可见性
– 保证有序性

1.4JMM如何保证三大特性
**原子性**
    基础类型
    x = 100 //能保证原子性
    y = x    //不能保证原子性
    y++    //不能保证原子性,反编译字节码文件,显示它拆成了三个步骤。
    **简单的放一起就不一定是原子的**
    volatile 不保证原子性

**可见性**
    volatile
    synchronized
    JUC里面的Lock

**有序性**
    volatile
    synchronized
    JUC里面的Lock

volatile语义
保证不同线程对share操作可见性
禁止对指令执行的顺序进行重排序

volatile vs synchronized
使用
volatile: 实例变量以及类变量,不能修改方法、局部变量
synchronized:不能修饰变量,只能修饰方法或者代码块
原子性
volatile不支持
可见性
OK
有序性
OK
其他
synchronized:block (悲观锁)
volatile不会线程阻塞

volatile使用场景:单列模式中,volatile+双重校验锁保证线程安全

1.5CAS操作,乐观锁

CAS: Compare-And-Swap 比较并交换

拿到内存中的最新值,使用CAS尝试将内存的值修改成目标值,如果修改失败,则获取该内存位置的最新值,然后重新尝试,直到修改成功,死循环

Unsafe很多方法都是native,直接调用JDK底层,性能高
直接操作内存,不受JVM管理

CAS:
缺点:开销大,CPU消耗高

1.5并发编程常见的工具类
  • CountDownLatch:火箭倒数计时发射。完成一个子线程减1,当为0,主线程运行。
  • CyclicBarrier: 集齐七颗龙珠召唤神龙。完成一个线程加一,当为指定数时,触发回调函数运行。
  • Semaphore: 占茅坑。类似于synchronized,但是它是能设置有多少个线程能同时的访问某段代码。

aqs(AbustactQueuedSynchronizer)同步队列 实现子类有:ReentrantLock、Semaphore、CountdowLatch

1.6Synchronized与Lock的区别

synchronized与Lock是java开发中最常见的所得使用

  • 对比
1.首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
2.synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
3.synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
4.用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
5.synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可)
6.Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
  • Synchronized 锁的到底是什么?
1、锁非静态方法时:锁住的是调用该方法的对象。针对当前new的对象
2、锁代码块时:锁住的是括号中Class对象。针对所有new的 对象

2.JVM

2.1JVM运行时五块区域

程序计数器、堆、栈、方法区、本地方法栈(运行时常量池 1.8移动到堆中)
https://www.cnblogs.com/sxdcgaq8080/p/7156227.html

2.2堆的常见调优参数
  • 初生代和幸存带比例:-XX:SurvivorRatio=8 ,默认8:1:1
  • 老年代和年轻代比列:-XX:NewRatio=2,默认2:1
  • 设置堆的最大最小值:-Xms2G -Xmx2G,默认配置一致防止内存抖动
  • 设置年老代使用CMSGC: -XX:+UseConcMarkSweepGC

https://blog.csdn.net/zqz_zqz/article/details/70568819

2.3GC范围

Minor GC:年轻代的GC
Major GC:老年代的GC
通常Major Gc前一般会进行Minor GC。 故有时Full GC和Major GC不怎么区分说法

2.4GCJDK1.7和JDK1.8的区别

1)Java1.8相对1.7,首先引入lamta表达式,
2)同时以元空间(Metaspace)取代永久代(PermGen),区别时元空间不在虚拟机中,故元空间内存大小只收本地内存影响。
3)HashMap数据结构由数组+链表(hash表)结构变成红黑二叉树,避免hash分布不均匀的问题

你可能感兴趣的:(JVM)