并发编程的锁机制:synchronized和lock
2020-04-27 本文已影响0人
Android_冯星
image.png
synchronized
- synchronized对于同步方法,锁是当前实例对象。
public synchronized void save(){}
- synchronized对于静态同步方法,锁是当前锁对象的Class对象。
public static synchronized void save(){//内容}
- synchronized对于同步方法块,锁是
Synchonized
括号里配置的对象。
public void save(String str){
//用的这个str对象来加锁
synchronized(str){
//内容
}
}
- synchronized后面括号里是类
synchronized后面括号里是类,如果线程进入,则线程在该类中所有操作不能进行,包括静态变量和静态方法,对于含有静态方法和静态变量的代码块的同步,通常使用这种方式。
public void save(String str){
synchronized(A.class){
//内容
}
}
Lock
Lock接口主要相关的类和接口如下。
image.pngReadWriteLock是读写锁接口,其实现类为ReetrantReadWriteLock。ReetrantLock实现了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方法
用于获取锁,如果锁被其它线程获取,线程处于等待状态。如果采用lock(),必须主动使用锁,如果发生异常,不会释放锁,所以lock必须try catch,在finally中释放锁,以防死锁发生。 -
lockInterruptibly方法
通过这个方法获取锁时,如果线程处于等待状态,中断线程等待状态。 -
tryLock方法
尝试获取锁,有返回值,获取到锁返回true,获取不到返回false,可以设置等待时间,在等待时间内获取到锁返回true,超时返回false。 -
unlock方法
释放锁 一定要在finally块中释放 -
newCondition方法
newCondition()返回Condition,Condition有两个作用:1.通过Condition对线程更精准控制线程的休眠与唤醒。2. 对于一个锁,我们可以为多个线程间建立不同的Condition
synchronized和lock的区别
- Lock是接口,synchronized是Java关键字。
- synchronized发生异常是自动释放锁,Lock不会自定释放锁,在lock发生异常时,如果没有unlock释放锁会造成死锁的现象,在使用Lock时需要在finally块中释放锁;
- Lock可以让等待的线程进行中断操作,synchronized不行,使用synchronized时,等待的线程会一直等待下去,不能响应中断。
- 通过Lock可以知道有没有获取到锁,而synchronized不知道。
- Lock可以提高多个线程进行读操作的工作效率(可以通过readwritelock实现读写分离)。
- 性能上来说,在资源竞争不激烈的情形下,Lock性能稍微比synchronized差点(编译程序通常会尽可能的进行优化synchronized)。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。