Synchronized和Lock的区别?
-
Synchronized是java里的关键字,Lock是类。
-
作用的位置不同
- Synchronized可以给方法,代码块加锁;
- Lock只能给代码块加锁。
-
锁的获取锁和释放机制不同
- Synchronized无需手动获取锁和释放锁,发生异常会自动解锁,不会出现死锁。
- Lock需要自己加锁和释放锁,如lock()和unlock(),如果忘记使用unlock(),则会出现死锁。所以一般我们会在finally里面使用unlock()。lock()和unlock()的数量保持一致,避免死锁。
-
synchronized是非公平锁,lock则默认是非公平锁,可设置为公平锁,如常用的ReentrantLock。
-
底层原理和性能角度分析:
-
synchronized锁是在对象的Markword中记录一个锁状态,锁标志位。
-
无锁,偏向锁,轻量级锁,重量级锁对应不同的锁状态。 根据资源竞争的激烈程度不断进行锁升级。
偏向锁: 只有一个线程争抢锁资源的时候.将线程拥有者标识为当前线程.
轻量级锁(自旋锁): 一个或多个线程通过CAS去争抢锁,如果抢不到则一直自旋.
重量级锁: 多个线程争抢锁,向内核申请锁资源,将未争抢成功的锁放到队列中直接阻塞.(当自旋的线程数量循环超过10次,或者线程等待的数量超过cpu的1/2,升级为重量级锁)锁的是什么?
-
ReentrantLock锁的是一个对象或者类。当一个线程获取了ReentrantLock锁后,其他线程需要等待该线程释放锁才能获取锁。ReentrantLock锁的特点是可重入的,也就是说同一个线程可以多次获取该锁。这意味着在一个线程已经获取了ReentrantLock锁的情况下,可以再次获取该锁而不会发生死锁。
-
锁竞争激烈的情况下,ReentrantLock性能高。
-
synchronized修饰成员方法时,默认的锁对象,就是当前对象;
-
synchronized修饰静态方法时,默认的锁对象,当前类的class对象,比如User.class;
-
synchronized修饰代码块时,可以自己来设置锁对象,比如
synchronized(this){
//线程进入,就自动获取到锁
//线程执行结束,自动释放锁
}
-