iis网站服务器 建立出现问题,吉林市城市建设档案馆官方网站,中国建设银行嵊州市支行网站,界面设计图片素材目录 1.什么是JMM
2.JMM怎样保障数据的可见性、有序性、原子性 2.1保证原子性 2.2.保证可见性 2.3保证有序性
3.CAS 3.1乐观锁和悲观锁 3.2 CAS介绍
4.重量级锁的自旋优化 1.什么是JMM JMM即Java内存模型 #xff0c;定义了一套在多线程读写共享数据#xff08;如数组、成…目录 1.什么是JMM
2.JMM怎样保障数据的可见性、有序性、原子性 2.1保证原子性 2.2.保证可见性 2.3保证有序性
3.CAS 3.1乐观锁和悲观锁 3.2 CAS介绍
4.重量级锁的自旋优化 1.什么是JMM JMM即Java内存模型 定义了一套在多线程读写共享数据如数组、成员变量等时对数据的可见性、有序性、原子性的规则和保障。JMM和Java内存结构关系不大内存结构就是JVM的内存组成、垃圾回收以及字节码和类加载的一些技术。
2.JMM怎样保障数据的可见性、有序性、原子性 2.1保证原子性 对于多个线程共享的数据而言如果不对数据进行加锁那么多个线程在调用同一资源时很可能出现异常操作。 比如线程1和线程2分别对一个初始值为0的变量 i 执行 i 和 i-- 操作理论上执行的结果是0但实际情况却不一定。由于操作系统在处理线程时采用的是时间片轮转的方式很有可能出现线程1还未执行完 i 时间片就耗尽了接下来就轮到线程2执行 i-- 操作。线程2在时间片内完成了对 i 的修改此时 i 的值为-1。然后再次轮到线程1由于线程1拿到的 i 的初始值是0所以 i 是在 i0 的基础上执行的执行完成后 i 的值为1覆盖掉了线程2的执行结果-1所以相当于线程2对于 i 的修改是无效的。 这就需要进行加锁当一个线程对一个共享资源未使用完毕前其他线程不能使用这一资源也就是保障了对共享资源的操作在执行完之前不会有其他线程访问这一资源。 加锁操作
synchronized(要加锁的对象){需要保障原子性的代码
} 锁粗化在加锁时要尽量扩大加锁的范围比如对变量 i 执行一千次加1操作如果仅对加一的操作进行加锁那么就会执行一千次加锁和解锁的操作但如果是对整个循环进行加锁不仅可以保证原子性而且只用执行一次加锁和解锁的操作能够缩短运行时间。 2.2.保证可见性 共享资源存储在主内存中当一个线程频繁读取某一资源时JIT即时编译器会进行优化将该资源的值存入到该线程工作内存中的高速缓存中后面再读取这个资源的值时会从这个高速缓存中读取虽然提高了效率但当对这一资源的值进行修改后还是会从高速缓存中读取之前的旧值导致线程对这个资源的修改不可见。 有两种方式保证可见性
使用synchronized加锁 在加锁时会清空工作内存中对所有共享资源的缓存强制要求到主内存中重新读取共享变量的值保证了拿到的共享变量的值是最新的。并且在解锁时无论是否对共享变量的值进行了修改都会将共享变量的值刷新回主内存以确保主内存中的共享变量的值是最新的。也可以直接调用System.out.println()因为执行输出操作时会调用到synchronized。 优点是既能确保原子性又能确保可见性缺点就是synchronized属于重量级的操作性能较低。
使用volatile关键字 对共享变量加上volatile关键字能够强制要求线程在读取共享变量的值时总是从主内存中读取保证了可见性。该方式性能较高但仅适用于一个写线程其他都是读线程的情况因为如果有多个写线程由于不能保证原子性就无法确定拿到的值是否是正确的。 2.3保证有序性 JVM在执行赋值操作时会根据指令是否耗时而进行指令重排在不影响结果的条件下调整指令的执行顺序但在并发执行时更改指令的执行顺序就可能会出现错误此时可以通过加上volatile关键字禁用指令重排来保证有序性。
3.CAS 3.1乐观锁和悲观锁 在介绍CAS之前先来了解一下乐观锁和悲观锁 3.2 CAS介绍 CAS即Compare And Swap是一种乐观锁的思想不使用synchronized对共享变量加锁通过volatile关键字的配合实现了无锁并发。原理是通过一个while循环不断尝试修改共享变量的值在循环时暂时存储该共享变量的原值和本线程修改后的值并通过compareAndSwap方法来判断该线程修改共享变量结束后存储的原值是否和当前共享变量的值相同。如果不同说明在该线程修改共享变量期间其他线程对共享变量的值进行了修改那么本次修改就是无效的需要再次进入循环重新获取共享变量的值并尝试修改如果相同说明修改期间其他线程并没有对共享变量进行修改那么就会将修改的结果更新到主内存中并返回true可以通过if语句实现跳出循环。 至于要volatile关键字的配合是因为要保证可见性在每次循环时都能获取到共享变量最新的值。 由于synchronized加锁会使线程进入阻塞并进行上下文切换需要保存线程阻塞前的状态并在被唤醒时恢复这一过程是非常耗时的所以CAS无锁并发能够提升效率但CAS适用于线程竞争不激烈并且是多核CPU的情况下因为当竞争比较激烈时肯定会进行频繁的循环此时就需要花费大量的时间来不断尝试修改共享变量的值而如果是单核CPU那么当时间片耗尽时只能等待下次拿到时间片时才能继续尝试但多核CPU就能实现在其他线程运行的同时不断尝试这才能体现CAS的优势。
4.重量级锁的自旋优化