问题:在32位的机器上对long型变量进行加减操作存在并发隐患,那么到底是不是这样的呢?
分析:long类型是64位,所以在32位机器上,对long类型的数据操作通常需要多条指令组合出来 ,无法保证原子性,所以并发的时候会出现问题。
对于JAVA并发编程中的一些问题:
可见性问题:
对于可见性,我们先看下定义:
可见性:一个线程对共享变量的修改,另外一个线程能够立刻看到。并发问题往往都是综合症,这里即使是单核CPU,只要出现线程切换就会有原子性问题。或许我们可以把线程对变量的读写都看作是原子操作,也就是CPU对变量的操作中间状态不可见,这样就能更加理解什么是可见性了。
CPU缓存刷新到时内存的时机:
CPU将缓存写入内存的时机是不确定的,除非你调用CPU相关指令强刷。
双重锁问题:
如果A线程与B线程同时进入第一个分支,那么这个程序就没有问题。
如果A线程先获取锁并出现指令重排序时,B线程未进入第一个分支,那么就可能出现空指针问题,这里可以说可能出现问题是因为当把内存地址赋值给共享变量后,CPU将数据写回缓存的时机是随机的。
synchronized:
线程在synchronized块中,发生线程切换,锁是不会释放的。
指令优化:
除了编译优化,有一部分可以通过看汇编代码来看,但CPU和解释器在运行期也会做一部分优化,所以很多时候都是看不到的,也很难重现的。
JVM模型和物理内存、缓存等关系:
内存、CPU缓存是物理存在的,JVM内存是软件存在的。关于线程的工作内存和寄存器、CPU缓存的关系,可以参看文章:
https://blog.csdn.net/u013851082/article/details/70314778/
IO操作:
IO操作不占用CPU,读文件,是设备驱动干的事情,CPU只管发命令。发完命令,就可以干别的事情了。
寄存器的切换:
寄存器是共用的,A线程切换到B线程的时候,寄存器会把操作A的相关内容会保存到内存里,切换回来的时候,会从内存把内容加载到寄存器。可以理解为每个线程有自己的寄存器。