一 Synchronized
synchronized是jvm提供的线程同步的机制,底层原理是:利用底层的一组monitor指令,在编译后把monitorenter插入同步代码段的开始,minitorexit插入同步代码段的结束位置,每次只允许一个线程进入同步代码段,从而达到线程同步的目的。
利用synchronized进行同步的几种情况:
-
synchronized同步代码段,锁住的是对象,能对同一个对象的方法进行同步,不能对两个不同的对象进行同步
synchronized(this){
//…
} -
synchronized同步方法,与同步代码块一样锁住的也是对象
public synchronized void func(){
//…
} -
同步一个类,即使同一个类的不同对象也能同步
synchronized(SynchronizedExample.class){
//…
} -
同步一个静态方法,锁住的是类
public synchronized static void func(){
//…
}
二 Lock:对代码块进行同步,利用lock()和unlock()
public class LockExample {
private Lock lock = new ReentrantLock();
public void func() {
lock.lock();
try {
//...
} finally {
lock.unlock(); // 确保释放锁,从而避免发生死锁。
}
}
}
- Lock里的方法
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
Condition newCondition();
}
三 Lock和Synchronized的区别
- 存在层面: synchronized是java关键字,属于jvm层面;lock是类,属于jdk层面
- 锁的释放条件:sync在执行完代码或发生异常自动释放锁;lock不会自动释放,容易造成死锁
- 锁的获取:sync中A,B两个线程,如果A获得锁,B等待,A阻塞的话,B会一直等待;
lock中有尝试获取锁的方法,如果尝试获取到锁,不会一直等待。 - 锁的状态:synchronized无法判断锁的状态;Lock可以判断。
- 锁的类型:sync是可重入,不可中断,非公平锁;lock是可重入,可中断,可公平锁
- 锁的性能:sync适用少量同步,性能开销大;lock适用大量同步情况:
*lock锁可以提高多个线程读的效率(readwritelock)
*竞争不激烈的情况下,sync优于lock,当竞争激烈时,sync性能下降几十倍,但reentrantlock性能维持常态
*Reentrantlock提供了多样化的同步,有时间限制的同步,可以被interrupt的同步(sync同步不能被中断)