内存模型和线程 你的名字 2022-04-03 06:16 220阅读 0赞 处理器快,其他太慢了,包括访存,加入高速缓存 高速缓存带来**缓存一致性**问题:同一块主存,各自的缓存不一样,缓存与主存交互时候需通过缓存一致性协议 jmm 屏蔽硬件和操作系统差异,定义(共享)变量访问规则 变量存在主存,线程操作变量必须工作内存中进行(包括volatile),工作内存含主存变量副本 低层次:**一般来说**,主存对应内存,工作内存对应寄存器和高速缓存 8原子操作 lock 将主内存变量标识为线程独占 unlock read 变量值**传到**工作内存 load 变量值**放入**工作内存变量副本中 use 变量值传给执行引擎,如放入操作栈顶(getstatic最后一步) assign 执行引擎传值给变量副本 store 变量值**传到**主存 write 变量值**放入**主存变量中 long和double的非原子性协定: **非volatile的**long,double可拆分两个32bit的操作(非原子性),有可能读到一个修改一半的数据,但很罕见,因为**实际虚拟机大多**还是实现成原子的。 变量只能在主存诞生, lock,清空工作内存此变量值,执行引擎使用前必须load或assign unlock之前必须把此变量同步回主存 volatile 可见性 禁止指令重排序(包括编译重排和乱序执行) 处理器重排序(乱序**执行**) jvm(jit)重排序 可见性:jmm规定volatile,use和read,load绑定,assign和store,write绑定 实现:汇编代码加入lock前缀指令相当于**内存屏障** 原子性:基本数据类型读写(6个原子操作,long,double不用太在意) lock/unlock monitorenter/monitorexit synchronized(大范围原子操作) synchronized原子性(A,B两个赋值操作,其它线程观测不到非原子的状态(A赋值B没有的情况),因为其它线程此时无法获取到锁) 可见性:volatile,synchronized(lock清空,unlock同步),final(不可变性使访问线程拿到的值肯定是对的,但发生**this引用逸出**导致第一次拿到的final域还没赋值,final就变化了) 有序性: **线程内表现为串行** 会有各种重排序,但在一个线程内感知不出来,因为重排序只发生在无依赖关系处 但其他线程观测到的是无序的,因为其他线程对**重排序变量有依赖关系**和**内存同步延迟** B观测A带来的**变化和影响**,这就是**有序的**(A**先行发生**于B,A **happens-before** B),没有先序发生,可任意重排序 程序次序(同一线程,A写在B前面,A happens-before B) 管程锁定(unlock happens-before **时间上后发生**的lock) volatile thread.start() thread.join()/isAlive() thread.interrupt() 对象构造 happens-before finalize() A happens-before B B happens-before C - A happens-before C **happens-before和发生时间前后无关** A时间先,但不happens-before(普通变量读写) Ahappens-before,但不时间先(指令重排序) 线程实现 内核线程:单个内核线程暴露给程序的接口是轻量级进程,我们程序就直接使用轻量级进程,1:1,(Sun jdk windows,linux 都是这种) 用户线程:**cpu时间分给进程**,进程内多个线程自己分配切换(自己得有线程库),1:N。 用户线程加轻量级进程:N:M 线程调度 协同式:必须线程主动放弃cpu 抢占式:系统分配时间,java 线程优先级:**建议**cpu时间多分少分,不太靠谱(依赖于操作系统,不同优先级可能最后映射成相同的,甚至系统会改变优先级) 状态:new,runnable,waiting,timed\_waiting,blocked,terminated blocked 获取排他锁 waiting 无限期等待 object.wait() thread.join() Locksupport.park() timed\_waiting thread.sleep() 带timeout的object.wait() 带timeout的thread.join() Locksupport.parkUtil() Locksupport.parkNanos()
还没有评论,来说两句吧...