Java面试题1:synchronized方法调用

来源:互联网 发布:微博爬虫java 编辑:程序博客网 时间:2024/06/05 03:33

1 synchronized同步方法调用另一个synchronized同步方法

public synchronized void methodA(int a, int b) {};public synchronized void methodB(int a){    methodA(a, 0);}

答:
要明白两个问题,①锁的对象是谁;②谁持有了锁。
有三种情况:
(1)假设方法A和B是在同一个类Test中的两个方法。

Test t = new Test(); t.methodB();

这个时候,methodB方法被调用时,因为加了synchronized ,需要先获得一个锁,这个锁的对象应该是t,也就是当前的这个Test类的实例,而获得锁的东西是线程,也就是说当前线程拿到了t的锁(而不是B方法获得锁),这个时候B方法内调用methodA,因为A也加了synchronized,也需要获得一个锁,因为A和B都是Test类中的方法,所以当前线程要获得的锁的对象也是t。由于当前线程在执行B方法时已经持有了t对象的锁,因此这时候调用methodA是没有任何影响的,相当于方法A上没有加synchronized。
加在非static方法上的synchronized方法是和synchronized(this)块等价的,均为对象锁,即对this加锁。获得当前对象锁的线程,可以继续获得当前对象锁,JVM负责跟踪对象被加锁的次数。线程运行B方法,此时如果this锁可以用,线程获得该锁,线程给对象加锁,计数器变成1,然后B方法调用A方法,由于是对同一个对象同一个线程,线程可以继续获得锁,计数器变为2,表示this被加锁2次。A方法完毕后,线程释放锁,计数器变为1,此时对象锁对其他线程依然是不可获得的。B方法完毕后,线程继续释放锁,此时计数器变为0,表示锁被完全释放,其他线程可以获得对象锁。

(2)假设现在有两个Test类

Test t1 = new Test(); Test t2 = new Test(); t1.methodB(); //此时当前线程持有了t1对象的锁t2.methodB(); //此时当前线程也持有了t2对象的锁

当前线程持有了两把锁,锁的对象分别是两个不同的Test类的实例t1和t2,互相没有影响。

(3)假设在多线程环境下,两个线程都可以访问Test t=new Test();
此时假设thread1里调用t.methodB();同时thread2里调用t.methodB()
这时假设thread1先抢到t对象的锁,那么thread2需要等待thread1释放t对象的锁才可以执行B方法。
结果像这样:
thread1获得t的锁->thread1执行methodB->thread1执行methodA->释放t的锁;
thread2获得t的锁->thread2执行methodB->thread2执行methodA->释放t的锁。

synchronized还有很多种使用方法,但只有明白是那条线程获得哪个对象的锁,就很容易明白了。

原创粉丝点击