java里面的锁常用的都有哪些;
常用的有synchronized(Object)、ReentrantLock(可重用锁)这些;
synchronized修饰一个静态类和静态方法和修饰一个非静态方法有什么区别吗?
Synchronized修饰非静态方法,俗称“对象锁”,要调用这个方法,必须创建这个对象,再来调用这个方法,因为一个类可以创建多个对象,而不同的对象就有不同的对象头,不同的对象头就有不同的锁,不同的锁用不同的线程创建的,他去调用这个方法的时候,他是不阻塞的,因为他们拿到的是不一样的锁。
Synchronized修饰静态方法,俗称“类锁”,因为类只有一个class文件,他在调用的时候是拿class类加锁,多个线程来调用这个方法的时候只有一把锁,所以执行完run方法之后他才会释放,下一个线程才可以拿到锁接着执行。
说说synchronized和ReentrantLock区别;
synchronized是可重用锁,他有俩种使用方式,方法或者代码块。加锁的话是传入一个人对象或者一个静态类,其实是对对象头进行一个操作,会把线程的id存储到对象头里面,线程在第二次调用这把锁的时候,他去判断这个id是不是锁里面的id,如果是的话他就可以直接操作。因为是jvm自己管理的,所以锁释放的话,当run方法执行完,也会直接释放。
ReentrantLock需要手动加锁和释放,首先我们要加锁,并在finally里面进行释放。和synchronized相比,ReentrantLock用起来会复杂一些。在基本的加锁和解锁上,两者是一样的,所以无特殊情况下,推荐使用synchronized。ReentrantLock的优势在于它更灵活、更强大,增加了轮训、超时、中断等高级功能
ReentrantLock的实现原理
ReentrantLock的使用
Lock lock = new ReentranLock();
lock.lock();
try{
//do something
}finally{
lock.unlock();
}
ReentrantLock实现了Lock接口,加锁和解锁都需要显式写出,注意一定要在适当时候unlock。
公平锁和非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
ReentrantLock的内部类Sync继承了AQS,分为公平锁FairSync和非公平锁NonfairSync。
- 公平锁:线程获取锁的顺序和调用lock的顺序一样,FIFO;
- 非公平锁:线程获取锁的顺序和调用lock的顺序无关,全凭运气。
ReentrantLock默认使用非公平锁是基于性能考虑,公平锁为了保证线程规规矩矩地排队,需要增加阻塞和唤醒的时间开销。如果直接插队获取非公平锁,跳过了对队列的处理,速度会更快。