美文网首页
线程八锁案例分析

线程八锁案例分析

作者: xhlc02 | 来源:发表于2020-04-15 11:31 被阅读0次

1.两个线程调用同一个对象的两个同步方法

public class ThreadDemo {

   public static void main(String[] args) {
       Phone phone = new Phone();
       new Thread(()->{
           phone.sendSms();
       },"A").start();
       new Thread(()->{
           phone.call();
       },"B").start();
   }

}
class Phone{
   /**
    * synchronized 锁的对象是方法的调用者!、
    * 两个方法用的是同一个锁,谁先拿到谁执行!
    */
   public synchronized void sendSms(){
       System.out.println("发短信");
   }
   public synchronized void call(){
       System.out.println("打电话");
   }
}

运行的结果如下

发短信
打电话

结果分析:被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法的调用者是同一个,所以两个方法用的是同一个锁,先调用方法的先执行。

2.新增Thread.sleep()给某个方法

public class ThreadDemo {

   public static void main(String[] args) {
       Phone phone = new Phone();
       new Thread(()->{
           phone.sendSms();
       },"A").start();
       new Thread(()->{
           phone.call();
       },"B").start();
   }
}
class Phone{
   /**
    * synchronized 锁的对象是方法的调用者!、
    * 两个方法用的是同一个锁,谁先拿到谁执行!
    */
   public synchronized void sendSms(){
       try {
           //睡眠4秒钟
           TimeUnit.SECONDS.sleep(4);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("发短信");
   }

   public synchronized void call(){
       System.out.println("打电话");
   }
}

// 等待4秒。
发短信
打电话

结果分析:被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法的调用者是同一个,所以两个方法用的是同一个锁,先调用方法的先执行,第二个方法只有在第一个方法执行完释放锁之后才能执行。

3.新增一个线程调用新增的一个普通方法

public class ThreadDemo {

   public static void main(String[] args) {
       Phone phone = new Phone();
       new Thread(()->{
           phone.sendSms();
       },"A").start();
       new Thread(()->{
           phone.call();
       },"B").start();
       new Thread(()->{
           phone.hello();
       },"C").start();
   }
}
class Phone{
   /**
    * synchronized 锁的对象是方法的调用者!、
    * 两个方法用的是同一个锁,谁先拿到谁执行!
    */
   public synchronized void sendSms(){
       try {
           //睡眠4秒钟
           TimeUnit.SECONDS.sleep(4);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("发短信");
   }

   public synchronized void call(){
       System.out.println("打电话");
   }

   /**
    *  这里没有锁!不是同步方法,不受锁的影响
    */
   public void hello(){
       System.out.println("hello");
   }
}

运行结果:

hello
//等待4秒
发短信
打电话

结果分析:新增的方法没有被synchronized修饰,不是同步方法,不受锁的影响,所以不需要等待。其他线程共用了一把锁,所以还需要等待。

4.两个线程调用两个对象的同步方法,并且睡眠其中一个

public class ThreadDemo {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 =new Phone();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone2.call();
        },"B").start();

    }
}
class Phone{
    /**
     * synchronized 锁的对象是方法的调用者!、
     * 两个方法用的是同一个锁,谁先拿到谁执行!
     */
    public synchronized void sendSms(){
        try {
            //睡眠4秒钟
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void call(){
        System.out.println("打电话");
    }

    /**
     *  这里没有锁!不是同步方法,不受锁的影响
     */
    public void hello(){
        System.out.println("hello");
    }
}

运行结果

打电话
//等待4秒
发短信

结果分析:被synchronized修饰的方法,锁的对象是方法的调用者。因为用了两个对象调用各自的方法,所以两个方法的调用者不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法。

5.增加两个静态的同步代码,同一个对象去调用不同的代码块

public class ThreadDemo {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 =new Phone();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone1.call();
        },"B").start();

    }
}
class Phone{
    /**
     * synchronized 锁的对象是方法的调用者!、
     * 两个方法用的是同一个锁,谁先拿到谁执行!
     * static 类一加载就有了!锁的是Class
     */
    public static synchronized void sendSms(){
        try {
            //睡眠4秒钟
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void call(){
        System.out.println("打电话");
    }


}

//等待4秒
发短信
打电话

结论:被synchronized和static修饰的方法,锁的对象是类的class对象,因为两个同步方法都被static修饰了,所以两个方法用的是同一个锁,后调用的方法需要等待先调用的方法

6.两个对象调用两个静态的同步方法

public class ThreadDemo {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 =new Phone();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone2.call();
        },"B").start();

    }
}
class Phone{
    /**
     * synchronized 锁的对象是方法的调用者!、
     * 两个方法用的是同一个锁,谁先拿到谁执行!
     * static 类一加载就有了!锁的是Class
     */
    public static synchronized void sendSms(){
        try {
            //睡眠4秒钟
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void call(){
        System.out.println("打电话");
    }
}

//等待4秒
发短信
打电话

结论:被synchronized和static修饰的方法,锁的对象是类的class对象,因为两个同步方法都被static修饰了,所以两个方法用的是同一个锁,后调用的方法需要等待先调用的方法

7.1个静态的同步方法,1个普通的同步方法 ,使用一个对象调用

public class ThreadDemo {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 =new Phone();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone1.call();
        },"B").start();

    }
}
class Phone{
    /**
     * synchronized 锁的对象是方法的调用者!、
     * 两个方法用的是同一个锁,谁先拿到谁执行!
     * static 类一加载就有了!锁的是Class
     */
    public static synchronized void sendSms(){
        try {
            //睡眠4秒钟
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    /**
     * 普通的同步方法  锁的调用者
     */
    public  synchronized void call(){
        System.out.println("打电话");
    }
}

打电话
//等待4秒
发短信

结论:被synchronized和static修饰的方法,锁的对象是类的class对象。仅仅被synchronized修饰的方法,锁的对象是方法的调用者。因为两个方法锁的对象不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法。

8.1个静态的同步方法,1个普通的同步方法 ,使用两个对象调用

public class ThreadDemo {

    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 =new Phone();
        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        new Thread(()->{
            phone2.call();
        },"B").start();

    }
}
class Phone{
    /**
     * synchronized 锁的对象是方法的调用者!、
     * 两个方法用的是同一个锁,谁先拿到谁执行!
     * static 类一加载就有了!锁的是Class
     */
    public static synchronized void sendSms(){
        try {
            //睡眠4秒钟
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    /**
     * 普通的同步方法  锁的调用者
     */
    public  synchronized void call(){
        System.out.println("打电话");
    }
}

打电话
//等待4秒
发短信

结论:被synchronized和static修饰的方法,锁的对象是类的class对象。仅仅被synchronized修饰的方法,锁的对象是方法的调用者。即便是用同一个对象调用两个方法,锁的对象也不是同一个,所以两个方法用的不是同一个锁,后调用的方法不需要等待先调用的方法。

总结:
1.一个类有多个synchronized 方法,被同一个对象调用时候,后来者必须进行等待,等待先来者释放才可以进行访问。
2.普通方法与同步方法无关
3.加入static修饰的方法,锁的是类
4.不同对象或者同一对象调用同一类中的不同静态同步代码块,后来者必须进行等待,等待先来者释放才可以进行访问。

相关文章

  • 线程八锁案例分析

    1.两个线程调用同一个对象的两个同步方法 运行的结果如下 发短信打电话 结果分析:被synchronized修饰的...

  • iOS-底层原理 29:锁的原理

    本文主要介绍常见的锁,以及synchronized、NSLock、递归锁、条件锁的底层分析 线程安全:线程安全:当...

  • CountDownLatch 分析

    参考 一行一行源码分析清楚AQSAQS 独占锁:只能有一个线程持有锁,获取锁失败的线程进入阻塞队列,持有锁的线程释...

  • java.util.concurrent---练习

    线程锁 生产者与消费者案例 循环打印ABC

  • iOS底层原理 - 八大锁分析

    回顾之前 前文讲到多线程原理,线程安全、线程阻塞、线程使用等;这节我们来分析一下有关线程安全的一部分:锁,线程锁。...

  • 方法锁、对象锁和类锁区别

    方法锁、对象锁和类锁区别 引言:结合synchronized进行分析。 synchronized用来处理多个线程同...

  • 死锁

    1.一个最简单的死锁案例当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么它们将永远被阻塞。在线程A...

  • MySQL锁+案例分析

    1. 概念梳理 根据加锁的范围,MySQL里面的锁大致可以分为:全局锁、表级锁、行锁三类。 1.1. 全局锁 全局...

  • Synchronized总结

    线程状态分析图 Synchronized的两种用法 对象锁:包括方法锁(默认对象锁为this当前实例对象)和同步代...

  • 2020-12-16-Spark-24(复习提纲)

    1.使用工具类时的多线程问题,多线程问题2.topN案例 组内排序案例的性能分析3.开窗案例再写一遍4.spark...

网友评论

      本文标题:线程八锁案例分析

      本文链接:https://www.haomeiwen.com/subject/rkpqvhtx.html