Synchronize_Integer

1

使用==的情况:
    • 如果比较Integer变量,默认比较的是地址值
    • Java的Integer维护了从-128~127的缓存池
    • 如果比较的某一边有操作表达式(例如a+b),那么比较的是具体数值
使用equals()的情况:
    • 无论是Integer还是Long中的equals()默认比较的是数值
    • Long的equals()方法,JDK的默认实现:会判断是否是Long类型
  • 注意自动拆箱,自动装箱问题。

2 锁消除

如果JVM明显检测到某段代码是线程安全的(言外之意:无锁也是安全的),JVM会安全地原有的锁消除掉!

Java面试题1:synchronized方法调用

1 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();12

这个时候,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对象的锁1234

当前线程持有了两把锁,锁的对象分别是两个不同的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还有很多种使用方法,但只有明白是那条线程获得哪个对象的锁,就很容易明白了。

问:

当一个线程进入一个对象的synchronized方法A之后,其它线程是否可进入此对象的synchronized方法B?

答:

不能。其它线程只能访问该对象的非同步方法,同步方法则不能进入。因为非静态方法上的synchronized修饰符要求执行方法时要获得对象的锁,如果已经进入A方法说明对象锁已经被取走,那么试图进入B方法的线程就只能在等锁池(注意不是等待池哦)中等待对象的锁。

拓展:

Java中,每个对象都有两个池,锁(monitor)池和等待池

wait() ,notifyAll(),notify() 三个方法都是Object类中的方法.

锁池:假设线程A已经拥有了某个对象(注意:不是类)的锁,而其它的线程想要调用这个对象的某个synchronized方法(或者synchronized块),由于这些线程在进入对象的synchronized方法之前必须先获得该对象的锁的拥有权,但是该对象的锁目前正被线程A拥有,所以这些线程就进入了该对象的锁池中。

等待池:假设一个线程A调用了某个对象的wait()方法,线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中,这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁),同时线程A就进入到了该对象的等待池中。如果另外的一个线程调用了相同对象的notifyAll()方法,那么处于该对象的等待池中的线程就会全部进入该对象的锁池中,准备争夺锁的拥有权。如果另外的一个线程调用了相同对象的notify()方法,那么**仅仅有一个处于该对象的等待池中的线程(随机)**会进入该对象的锁池.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值