在学习JVM的时候,都会记住这样几个概念:
- 栈是线程私有的。
- 每个方法的调用对应着栈桢的入栈出栈。
- 每个栈帧包含局部变量表、操作数栈以及指向当前方法所属类的运行时常量池的引用。
- 局部变量是线程安全的
这些概念都不难理解也不难记住,不过吧总觉得这些就是干巴巴的概念,背下来也就过去了。今天突然意识到其实在看到这些相关概念前,就已经见到他们的身影并受到其恩惠了。
平时都有debug程序,而debug模式下可以看到调用栈信息,最开始学习debug的时候当时带我的同事就跟我说在Frames这里是debug调用栈,蓝色选中的就是当前程序停留的位置,它往下依次是调用的方法信息。右侧Variables就可以看到当前的变量信息。当时觉得很神奇但现在想想,调用栈里的每一层不对应着一个栈桢,然后variables中的值就是对应栈桢中存储的元素。
下面用一段死锁的demo来验证一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class DeadLock { private static final Object o1 = new Object(); private static final Object o2 = new Object(); public static void main(String[] args) throws Exception{ ExecutorService threadPool = Executors.newFixedThreadPool(2); threadPool.submit(new Runnable() { @Override public void run() { int variableA = 10; synchronized (o1){ System.out.println("thread:=="+Thread.currentThread()+"拿到o1资源"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o2){ System.out.println("thread:=="+Thread.currentThread()+"拿到o2资源"); } } } }); threadPool.submit(new Runnable() { @Override public void run() { int variableA = 20; synchronized (o2){ System.out.println("thread:=="+Thread.currentThread()+"拿到o2资源"); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (o1){ System.out.println("thread:=="+Thread.currentThread()+"拿到o1资源"); } } } }); threadPool.shutdown(); } }
|