一、Java内存模型
1.概念
Java内存模型可以理解为Java内存访问模型。主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。
2.原理
1)名词解释
主内存:所有变量都存储到主内存。
工作内存:每条线程都有自己的工作内存,线程的工作内存中保存了该线程使用到的变量的主内存副本拷贝。
2)线程操作内存原理
a)线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存中的变量。
b)不同线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
3)线程操作内存实现手段
a)lock:作用于主内存的变量,它把一个变量标识为一条线程独占的状态;
b)unlock:作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放出来后的变量才可以被其他线程锁定;
c)read:作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用;
d)load:作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中;
e)use:作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎;
f)assign:作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量;
g)stroe:作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作;
h)write:作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中;
3.Java同步修饰符
1.volatile
Java虚拟机提供的最轻量级的同步机制。当一个变量定义为volatile之后,它将具备两种特性:
1)保证此变量对所有线程的可见性,这里的“可见性”是指当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得知的。而普通变量做不到这一点。但是Java里面的运算并非原子操作,导致volatile变量的运算在并发下一样是不安全的。
2)禁止指令序列优化
使用场景:
由于volatile变量只能保证可见性,仅当符合下面两条规则时才是线程安全的:
1)运算结果并不依赖变量的当前值,或者能够保证只有单一的线程修改变量的值
2)变量不需要与其他的状态变量共同参与不变约束
2.synchronized
万能
3.final
线程安全。
Java与线程
1.Java线程调度
1)协同式调度:线程的执行时间由线程本身来控制,线程把自己当工作执行完之后,要主动通知系统切换到另一个线程上。缺点:bug或恶意线程会导致当前线程一直占用资源,导致程序阻塞。
2)抢占式调度:每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定。当然也提供了部分操作来控制线程的调度:
a)让出执行时间:Thread.yield()
b)给线程多分配时间:通过线程的优先级去设定
2.线程状态切换
一个线程只能处于其中的一种状态:
1)新建(new):创建后尚未启动的线程处于此状态;
2)运行(Runable):包括操作系统中的Running和Ready,即此状态的线程可能正在执行,也可能正在等待CPU为它分配执行时间;
3)无限期等待(Waiting):此状态的线程不会被分配CPU执行时间,他们需要等待被其他线程显式唤醒。以下方法可让线程处于无限期等待状态:
a)没有设置Timeout参数的Object.wait()方法
b)没有设置Timeout参数的Thread.join()方法
c)LockSupport.park()方法
4)限期等待(Timed Waiting):此状态的线程也不会被分配CPU执行时间,不过无需等待被其他线程显式唤醒,在一定时间之后他们会由系统自动唤醒。以下方法可让线程处于限期等待状态:
a)Thread.sleep()
b)设置了Timeout参数的Object.wait()方法
c)设置了Timeout参数的Thread.join()方法
d)LockSupport.parkNanos()
e)LockSupport.parkUntil()
5)阻塞(Blocked):在程序等待进入同步区域的时候,线程将进入这种状态。阻塞状态是在等待着获取到一个排它锁,这个事件将在另外一个线程放弃这个锁的时候发生;
6)结束(Terminated):线程执行结束
5.png
网友评论