欢迎关注微信公众号:互联网全栈架构
上次创建了一个投票,针对并发编程中常用的关键字synchronized,它到底能不能锁住局部变量,有50%的人认为可以,另外一半认为不可以,具体情况可参见之前的文章:Synchronized能锁住局部变量吗?。
而正确答案是不可以,因为局部变量是存放在栈中,而每个线程都有自己的栈空间,也就是说局部变量是线程私有的,使用线程对局部变量加锁,并不会影响其它线程对于代码块的访问,下面我们用实例来验证一下。
还是之前的代码片段,只不过启用两个线程来分别调用:
package com.sample.core.multithread;
public class MultiThreadDemo {
public static void main(String[] args) {
MultiThreadDemo demo2 = new MultiThreadDemo();
Thread t1 = new Thread(() -> demo2.testSync());
Thread t2 = new Thread(() -> demo2.testSync());
t1.start();
t2.start();
}
private int count = 0;
public void testSync(){
String str = new String("test");
synchronized (str){
for (int i = 0; i < 10; i++) {
count++;
}
}
}
}
可以看到,synchronized关键字锁住的对象是str,它是一个局部变量。在for循环那里加一个断点,然后debug这个程序:
线程Thread-0的状态为RUNNING,它正在运行,单步调试,程序可以继续往下运行。在下拉框中选择Thread-1,发现它的状态也是RUNNING:
第一个线程进入synchronized代码块以后,第二个线程也还可以进入,说明对于局部变量加锁根本就没有起作用。我们把变量str提出来作为类的成员变量,再看看是什么情况:
package com.sample.core.multithread;
public class MultiThreadDemo {
public static void main(String[] args) {
MultiThreadDemo demo2 = new MultiThreadDemo();
Thread t1 = new Thread(() -> demo2.testSync());
Thread t2 = new Thread(() -> demo2.testSync());
t1.start();
t2.start();
}
private int count = 0;
String str = new String("test");
public void testSync(){
synchronized (str){
for (int i = 0; i < 10; i++) {
count++;
}
}
}
}
还是在for循环那里设置一个断点,然后debug程序,可以看到Thread-0是RUNNING的状态:
切换到Thread-1,可以看到它的状态是MONITOR,也就是处于阻塞的状态,只有等Thread-0执行完成以后才能继续执行:
所以,通过上面的代码示例可以看出,synchronized对于局部变量加锁是没有任何作用的,只有对于类的成员变量加锁,才能达到我们想要的效果。
创作不易,烦请点赞、分享,感谢!
推荐阅读: