Object obj=new Object();
Object obj2=obj;
synchronized(obj){}
synchronized(obj2){}
又如果这样呢?
Object obj=new Object();
synchronized(obj){}
obj=new Object();
synchronized(obj){}
Object obj=new Object();
Object obj2=obj;
synchronized(obj){}
synchronized(obj2){}
又如果这样呢?
Object obj=new Object();
synchronized(obj){}
obj=new Object();
synchronized(obj){}
锁这个标记是在 对象的Header的markword中存在的,是和一个对象绑定的,而不是和对象的引用绑定,所以第一个问题是互斥的,你的第二个问题有问题,因为你写synchronized(obj){}的时候,一般是以内部类的形式写在runnable或者Thread中,但是内部类引用的外部变量就必须是final的,而你这个obj都变了,就不是final,所以这段代码你是咋写出来的?
针对问题:如果多个线程在并发执行执行拥有相同锁的同步块synchronized(obj){}时,锁对象obj被另一个线程给修改了指向,这个同步是否会失效?我有测试过这种情况没有失效,可能是因为即便obj引用指向变了,当前还没有执行完的同步块之间还是互斥的,因为对象还没有被回收还在使用中。如果只有一个同步块没有执行完,修改obj指向后,又执行了一个synchronized(obj){},这个时候它们是不是互斥的呢?
测试代码:
static Object obj=new String("a");
public static void main(String[] args) throws InterruptedException {
class a extends Thread{
@Override
public void run() {
synchronized(obj){
for (int i = 0; i < 10000; i++) {
if(i%10==0)System.out.println(obj+",0");
}
}
}
}
new a().start();
Thread.sleep(10);
obj=new String("b");
class b extends Thread{
@Override
public void run() {
synchronized(obj){
for (int i = 0; i < 10000; i++) {
if(i%10==0)System.out.println(obj+",1");
}
}
}
}
new b().start();
}
测试结果:两个线程输出有交叉,同步确实会失效
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4.1k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
上面两个 synchronized 块是互斥的.
所以基于这种锁对象可能被误用的情况, 建议用单独的 final 对象做锁, 而不要用与业务相关的变量: