static和synchronized

static和synchronized

2个线程模拟手机发邮件和发短信功能

八锁

  • 标准访问 2个线程 一部手机资源类
  • 发邮件睡眠4
  • 新增sayHello方法
  • 两部手机资源类
  • 2个静态同步方法 一部手机
  • 2个静态同步方法 两部部手机
  • 1个静态同步方法 一个普通同步方法 一部手机
  • 1个静态同步方法 一个普通同步方法 两部部手机

场景一

标准访问 2个线程 一部手机资源类

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
     synchronized void sendEmail() {
        System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }


}

结果

1574948896560

场景二

发邮件睡眠4

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
     synchronized void sendEmail() {
         try {
             TimeUnit.SECONDS.sleep(4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }

         System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }
}

结果

synchronized锁的当前对象,一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其它线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法

1574948896560

场景三

新增sayHello方法

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone.sayHello();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
     synchronized void sendEmail() {
         try {
             TimeUnit.SECONDS.sleep(4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }

         System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello(){
        System.out.println("sayHello------>");
    }
}

结果

加个普通方法后发现和同步方法无关

1574949724372

场景四

两部手机资源类

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone2.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
     synchronized void sendEmail() {
         try {
             TimeUnit.SECONDS.sleep(4);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }

         System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello(){
        System.out.println("sayHello------>");
    }


}

结果

换成两个对象后,不是同一把锁,情况立刻发生了变化,所有的非静态同步方法用的都是同一把锁,即实例对象本身

1574949828714

场景五

2个静态同步方法 一部手机

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone.sendSMS();
//            phone2.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
    static synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("sendEmail----->");
    }

    //发短信
    static synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello() {
        System.out.println("sayHello------>");
    }
}

结果

synchronized实现同步的基础,java中的每一个对象都可以作为锁,具体表现以下3种形式

  • 对于普通同步方法,锁是当前实例对象
  • 对于同步方法块,锁是synchronized括号里配置的对象
  • 对于静态同步方法,锁是当前类的Class对象

1574948896560

场景六

2个静态同步方法 两部部手机

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
//            phone.sendSMS();
            phone2.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
    static synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("sendEmail----->");
    }

    //发短信
    static synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello() {
        System.out.println("sayHello------>");
    }


}

结果

1574948896560

场景七

1个静态同步方法 一个普通同步方法 一部手机

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
            phone.sendSMS();
//            phone2.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
    static synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello() {
        System.out.println("sayHello------>");
    }
}

结果

1574949828714

场景八

1个静态同步方法 一个普通同步方法 两部部手机

package com.zbiti.juc;

import java.util.concurrent.TimeUnit;

public class LockDemo {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();
        Phone phone2 = new Phone();

        new Thread(() -> {
            phone.sendEmail();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(2);

        new Thread(() -> {
//            phone.sendSMS();
            phone2.sendSMS();
        }, "BB").start();
    }
}

//手机资源类,带发邮件、发短信功能
class Phone {
    //发邮件
    static synchronized void sendEmail() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("sendEmail----->");
    }

    //发短信
    synchronized void sendSMS() {
        System.out.println("sendSMS------->");
    }

    void sayHello() {
        System.out.println("sayHello------>");
    }
}

结果

锁当前实例对象和锁当前类的Class对象是两个不同的对象,所以静态同步方法和非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其它的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象静态同步方法之间

1574949828714


 上一篇
多线程间通信 多线程间通信
多线程并发,主要是多线程操作资源类,其次是多线程间的通信,三部曲,判断、干活、通知,为了防止虚假唤醒判断时必须使用while,最后,为了保证多线程执行的顺序性,可以使用Condition配合标志位来通知唤醒指定线程。 生产者消费者两个线
2019-11-29
下一篇 
集合类不安全 集合类不安全
集合类不安全ArrayList集合类不安全 故障现象java.util.ConcurrentModificationException 导致原因 多线程对集合的并发操作导致并发修改异常的产生 解决方案 Vector(加synchroniz
2019-11-28
  目录