synchronize 的对象修改还能锁定吗?
今天在坐动车时候忽然想到一个奇怪的问题,如果synchronize锁定对象被修改,那么是否锁就失效下面分为两种情况。
对象属性被修改
代码很简单,主要是一个线程请求一个已经被锁住10秒的对象,如果获得锁就输出已经获得。
public class User {
private Integer age ;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public User(Integer age) {
this.age = age;
}
public User() {
}
}
public class Test {
public static User o1 = new User();
public static void main(String[] args) {
Thread keep = new Thread(()->{
synchronized (o1){
System.out.println("我占用了O1锁了: "+Thread.currentThread().getName());
try {
Thread.sleep(10000L);
System.out.println("我用好了");
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"占用线程");
Thread get = new Thread(()->{
System.out.println("开始工作: "+Thread.currentThread().getName());
o1.setAge(22); //对象的属性修改
synchronized (o1){
System.out.println("获得锁后进行执行");
}
},"工作线程");
keep.start();
get.start();
}
}
执行结果:
可以看到请求的线程还是等它用完了之后再执行自己的逻辑,所以对象属性被修改并不影响锁的稳定性。
对象修改
重复的代码这里不重复写了,这里对上面的o1.setAge(22); //对象的属性修改
这一行代码进行修改变成o1=new User();
结果如下:
这里可以看到获取线程并没有等待10秒执行完输出后执行,所以更换了对象就相当于换了一把锁,并不影响执行。
所以在我们的IDE里面调用这个对象的时候会提示
所以一些不需要修改的对象还是定义成final比较安全,毕竟不可变的东西永远是线程安全的呀~