并发编程的锁机制:synchronized和lock

image.png

synchronized

Java中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.png

ReadWriteLock是读写锁接口,其实现类为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的区别

  1. Lock是接口,synchronized是Java关键字。
  2. synchronized发生异常是自动释放锁,Lock不会自定释放锁,在lock发生异常时,如果没有unlock释放锁会造成死锁的现象,在使用Lock时需要在finally块中释放锁;
  3. Lock可以让等待的线程进行中断操作,synchronized不行,使用synchronized时,等待的线程会一直等待下去,不能响应中断。
  4. 通过Lock可以知道有没有获取到锁,而synchronized不知道。
  5. Lock可以提高多个线程进行读操作的工作效率(可以通过readwritelock实现读写分离)。
  6. 性能上来说,在资源竞争不激烈的情形下,Lock性能稍微比synchronized差点(编译程序通常会尽可能的进行优化synchronized)。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态。

你可能感兴趣的:(并发编程的锁机制:synchronized和lock)