Synchronized总结

2019-06-12  本文已影响0人  乔治m2

锁的类型

对象锁

  1. 同步代码块锁,所有的实例化对象各自带有一把锁(this)

    sychronized(this) {
        
    }
    
  2. 普通方法上带有synchronized修饰,默认使用本对象作为锁

    public synchronized void test() {
        
    }
    

类锁

  1. 静态方法锁(使用class唯一对象作为锁)

    public static synchronized test() {
        
    }
    
  2. 同步代码块,锁对象为.class对象

    synchronized(xxx.class) {
        
    }
    

多线程访问同步锁的七种情况

  1. 两个线程同时访问一个同步对象的同步方法

    答:串行执行方法,两个线程依次拿到当前同步方法的锁。

  2. 两个线程访问的是两个对象的同步方法

    答:分情况:如果两个对象使用的是类锁,那么是串行执行方法,如果两个对象的方法使用的是当前对象锁,那么并行执行方法。

  3. 两个线程访问的是synchronized的静态方法

    答:串行执行方法,由于是synchronized修饰的静态方法默认实现类锁,所有多线程执行为串行。

  4. 同时访问同步方法和非同步方法

    答:并行执行方法,由于非同步方法不受同步方法的限制,所以多线程执行方法的时候不会受到锁的影响。

  5. 同时访问一个对象的不同的普通同步方法

    答:串行执行方法,由于普通的同步方法默认使用本对象为锁,在者这里多线程访问的是同一个对象,所以锁是相同的,所以会串行执行方法。

  6. 同时访问静态synchronized和非静态的synchronized方法

    答: 并行执行方法,由于静态的synchronized使用本类作为锁,而非静态的synchronized使用本对象作为锁,锁不同,多线程执行的时候不会相互受到影响,所以并行执行方法。

  7. 方法抛出异常后会释放锁。

七种情况总结,3点核心思想

  1. 一把锁同时只能被一个线程获取,没有拿到锁的线程必须等待。
  2. 每个实例都应有自己的一把锁,不同实例之间互不影响;锁对象是*.class或者synchronized修饰的是static静态方法的时候,所有对象共用一把锁。
  3. 无论是方法正常结束或者抛出异常,都会释放锁。

使用注意点

  1. 锁对象不能为空。
  2. 作用域不宜过大。
  3. 避免死锁。

如何选择Lock和synchronized关键字

  1. 在程序中如果能不使用同步,就劲量不使用这两个关键字,优先选择java.util.concurrent包下的类。
  2. 能用synchronized解决的方法就劲量选择synchronized
  3. 如果需要Lock独有的特性的时候,才使用Lock.
上一篇 下一篇

猜你喜欢

热点阅读