jvm运行时内存区域:
- native method栈(与底层系统的方法)
- 虚拟机栈(局部变量、参数、方法、对象引用,线程私有)
- 堆(对象实例,GC堆,线程共享)
- 程序计数器(记录每个线程执行的字节码行数,方便线程切换,本地方法不记录,线程私有)
- 方法区(静态变量、常量、静态方法、类信息,线程共享)
- 常量池(类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,线程共享)
java线程是(内核控制线程:又称轻型进程lwp(light weight process))
java线程是混合型的线程模型,一般而言是通过lwp将用户级线程映射到内核线程中。意味着用户能够控制线程的分配和启停,也意味着内核能够感知调度线程,利用多核cpu处理,有自己的存储区域(保存寄存器、程序计数器、栈指针等)
多线程的竞态争夺,导致数据被重复读写以及操作
jvm内存模型使用屏障的方法,保证指令的顺序,例如锁、voilate等。
CPU指令重排序造成多个线程数据脏读
jvm内存模型使用屏障的方法,保证指令的顺序,例如锁、voilate等。
java多线线程voilate 保证可见性
当线程1修改变量后,强制执行store和wirte操作,将工作内存的值保存到主内存(运行时数据区中的堆内)
当线程2读取变量是,强制废弃之前的变量,执行read,将主内存的数据读取到工作内存
synchronized 方法
原理类似于voilate,但比voilate更加重量级,性能开销大
两种写法获取对象实例锁:synchronized method(){} synchronized(object){}
若用在静态方法上则会获取整个所有实例起作用
wait()释放锁,线程进入等待状态;notify() notifyall()通知wait状态线程获取锁;sleep()进入等待,但不会释放锁;interrupt()是线程重新获取锁,但会抛出异常。
ReentrantLock(同样为线程的可重入锁,但是具有公平锁、锁等待、需要手动释放锁、手动处理异常等)
reetrantlock在控制线程上颗粒度更细,例如在阻塞队列中,通过condition的控制,可以指定是消费线程还是生成线程重等待中启动,对比与sychronized的随机唤醒线程,节约了时间。
ThreadLocal
ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。
包装类型(integer\string\double等)在函数传参过程(实际还是引用传递)或者多线程中使用时会重新分配内存(若值发生变化),这样导致锁是无效的。
包装类型本质是个不可变类,由final进行修饰,当进行改变时,会重新分配内存赋值。