并发编程小记---5.17
final类型的特点final 变量赋值后不能改引用地址不可变final 方法不能被子类重写final 类不能被继承引用类型Java 数据类型就两种基本数据类型byte short int long float double char boolean引用数据类型除了上面 8 种剩下全是引用类型基本类型变量里直接存真实值引用类型变量里不存真实对象只存对象在堆内存的地址引用打个比方基本类型手里直接拿着苹果引用类型手里拿的是地址纸条苹果放在仓库堆内存里常见引用类型有哪些类自己定义的类、String、Date接口数组数组永远是引用类型集合List、Map、Set等想要子线程修改主线程的共享变量、并且主线程能感知到必须用引用类型。如果用基本类型子线程改不了主线程的变量。基于其他线程计算结果上进行计算怎么计算结果一定是正确的利用synchronized保证写后读想要基于其他线程结果计算不出错一定要等前置线程执行完毕再取值计算不要并发抢跑。synchronized关键字的对象锁机制一次只能调用一个当一个线程进入任意一个加了synchronized的方法时它会拿到这个对象的锁其他线程想调用这个对象上的任何synchronized方法都必须等待锁被释放直到第一个线程执行完方法、退出临界区锁才会被释放其他线程才有机会拿到锁执行synchronized一定要在写以后再释放否则可能无效!!多进程、多线程、多服务器保证结果对一定是写后读一、Lock 指令一、Lock 前缀指令的核心作用Lock前缀指令是处理器实现原子性操作的底层保障主要作用有两点强制缓存回写触发处理器将修改后的缓存数据写回主内存。保证独占访问在多处理器环境中通过LOCK信号确保指令执行期间处理器对共享内存的独占访问从而保证操作的原子性。二、处理器锁机制的演进从总线锁到缓存锁处理器 / 架构锁实现方式特点Intel 486 / Pentium总线锁锁操作时始终在总线上声明LOCK信号锁定整个系统总线开销大。P6 架构及现代处理器缓存锁优化方案若访问的内存区域已在处理器缓存中则不锁总线而是1. 锁定该内存区域对应的缓存行2. 修改后直接回写内存3. 利用缓存一致性协议保证原子性开销远低于总线锁三、缓存锁的工作原理触发条件当处理器检测到操作的内存地址已被自身缓存时会自动启用缓存锁而非总线锁。核心机制依赖缓存一致性协议如 MESI阻止多个处理器同时修改同一内存区域的缓存副本从而在缓存层面实现独占访问。优势仅锁定单个缓存行不影响其他内存区域的访问大幅降低锁操作的性能开销。四、关键概念总结总线锁早期处理器实现原子性的粗暴方式锁定整个系统总线所有处理器都无法访问内存性能开销极大。缓存锁现代处理器的优化方案利用缓存一致性协议锁定单个缓存行仅影响被修改的数据性能开销大幅降低。LOCK信号总线锁的核心信号用于在总线上声明独占访问现代处理器仅在无法使用缓存锁时如跨多个缓存行才会触发。二、volatile优化原理AtomicReference通过追加变量把共享变量的总大小填充到64 字节。计算对象引用占 4 字节加上 15 个填充变量共 60 字节再加上父类的value变量刚好凑齐 64 字节。缓存行的特性英特尔酷睿 i7/Atom/Core Solo/Pentium M 等处理器的L1/L2/L3 缓存行宽度为 64 字节且不支持部分填充缓存行。若两个变量比如队列的头节点和尾节点加起来不足 64 字节它们会被读入同一个缓存行。伪共享的危害当多个处理器分别修改这两个变量时会触发缓存一致性协议的锁定机制。修改其中一个变量时会锁定整个缓存行导致其他处理器无法访问另一个变量。对于队列这种频繁修改头 / 尾节点的场景会严重降低入队 / 出队效率。缓存行填充的解决思路用额外的字节将变量占满整个 64 字节缓存行让头节点和尾节点分别位于不同的缓存行中。这样修改时只会锁定各自的缓存行不会互相干扰大幅提升并发性能。利用 64 字节缓存行的特性通过填充变量让共享变量独占缓存行避免多线程修改时的缓存行竞争从而提升并发效率但它不是万能的需要结合处理器架构和变量的访问频率来决定是否使用。三、synchronized 的三种锁形式Java 中每一个对象都可以作为锁具体分为 3 种场景场景锁对象特点普通同步方法当前实例对象this不同实例的锁互不影响同一实例的同步方法互斥静态同步方法当前类的Class对象所有实例共享同一把锁全局互斥同步代码块synchronized(...)括号内指定的对象锁粒度更灵活可自定义锁对象JVM 底层实现原理synchronized基于Monitor监视器对象实现同步代码块和方法的实现细节不同同步代码块编译后在同步代码块的开始位置插入monitorenter指令在同步代码块的结束位置和异常处理位置插入monitorexit指令JVM 保证每个monitorenter必须有对应的monitorexit指令配对确保锁一定会被释放同步方法JVM 规范未明确其具体实现细节但同样可以通过monitorenter/monitorexit指令实现也存在其他优化实现方式Monitor 与锁的关系每个 Java 对象都与一个Monitor对象关联当Monitor被线程持有后会进入锁定状态线程执行monitorenter指令时会尝试获取该对象对应Monitor的所有权也就是获取对象锁同一个类的静态同步方法不能被多个线程同时调用而非静态的普通静态方法不加synchronized完全可以被多个线程同时调用。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2626809.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!