JavaSE之8锁现象线程彻底理解锁

8锁现象线程彻底理解锁

利用8道题,彻底搞定锁

1.问题一

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

/*
1、标准的访问情况下,先执行 sendEmail 还是 sendSMS

   答案:sendEmail
   被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个
   先调用的先执行!
 */
public class LockDemo01 {
    public static void main(String[] args) throws InterruptedException {
        Phone phone = new Phone();

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

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(2);

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

class Phone{
    public synchronized void sendEmail(){
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS(){
        System.out.println("sendSMS");
    }
}

2.问题二

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

/*
2、sendEmail休眠3秒后 ,先执行 sendEmail 还是 sendSMS

   答案:sendEmail
   被 synchronized 修饰的方式,锁的对象是方法的调用者,所以说这里两个方法调用的对象是同一个
   先调用的先执行!
 */
public class LockDemo02 {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone = new Phone2();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(2);

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

class Phone2{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS(){
        System.out.println("sendSMS");
    }
}

3.问题三

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

/*
3、增加一个普通方法,请问先打印那个 sendEmail 还是 hello

   答案:hello
   新增加的这个方法没有 synchronized 修饰,不是同步方法,不受锁的影响!
 */
public class LockDemo03 {
    public static void main(String[] args) throws InterruptedException {
        Phone3 phone = new Phone3();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

        new Thread(()->{
            phone.hello();
        },"B").start();
    }
}

class Phone3{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }

    // 没有 synchronized 没有 static 就是普通方式
    public void hello(){
        System.out.println("hello");
    }
}

4.问题四

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

/*
4、两个手机,请问先执行sendEmail 还是 sendSMS
    答案:sendSMS
    被 synchronized  修饰的方式,锁的对象是调用者;我们这里有两个调用者,两个方法在这里是两个锁
 */
public class LockDemo04 {
    public static void main(String[] args) throws InterruptedException {
        Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();

        new Thread(()->{
            try {
                phone1.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

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

class Phone4{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS(){
        System.out.println("sendSMS");
    }
}

5.问题五

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

//LockDemo05.Class 模板,只有一个     static
//new LockDemo05(),可以创建多个对象

/*
5、两个静态同步方法,同一个手机请问先执行sendEmail 还是 sendSMS

    答案:sendEmail
    只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁
    并不是因为synchronized
 */
public class LockDemo05 {
    public static void main(String[] args) throws InterruptedException {
        Phone5 phone = new Phone5();


        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

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

class Phone5{

    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public static synchronized void sendSMS(){
        System.out.println("sendSMS");
    }

}

6.问题六

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

//LockDemo05.Class 模板,只有一个     static
//new LockDemo05(),可以创建多个对象

/*
6、两个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS

    答案:sendEmail
    只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!所以说这里是同一个锁
    并不是因为synchronized
 */
public class LockDemo06 {
    public static void main(String[] args) throws InterruptedException {
        Phone6 phone = new Phone6();
        Phone6 phone2 = new Phone6();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

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

class Phone6{

    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public static synchronized void sendSMS(){
        System.out.println("sendSMS");
    }

}

7.问题七

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

//LockDemo05.Class 模板,只有一个     static
//new LockDemo05(),可以创建多个对象

/*
7、一个普通同步方法,一个静态同步方法,只有一个手机,请问先执行sendEmail 还是 sendSMS

    答案:sendSMS
    synchronized 锁的是这个调用的对象
    static 锁的是这个类的Class模板
    这里是两个锁!
 */
public class LockDemo07 {
    public static void main(String[] args) throws InterruptedException {
        Phone7 phone = new Phone7();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

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

class Phone7{

    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS(){
        System.out.println("sendSMS");
    }

}

8.问题八

package com.coding.lock8;

import java.util.concurrent.TimeUnit;

//LockDemo05.Class 模板,只有一个     static
//new LockDemo05(),可以创建多个对象

/*
7、一个普通同步方法,一个静态同步方法,两个手机,请问先执行sendEmail 还是 sendSMS

    答案:sendSMS
    synchronized 锁的是这个调用的对象
    static 锁的是这个类的Class模板
    这里是两个锁!
 */
public class LockDemo08 {
    public static void main(String[] args) throws InterruptedException {
        Phone8 phone = new Phone8();
        Phone8 phone2 = new Phone8();

        new Thread(()->{
            try {
                phone.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        //Thread.sleep(200);
        TimeUnit.SECONDS.sleep(1);

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

class Phone8{

    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

    public synchronized void sendSMS(){
        System.out.println("sendSMS");
    }

}

小结

1、new this 调用的这个对象,是一个具体的对象!

2、static class 唯一的一个模板!

在我们编写多线程程序得时候,只需要搞明白这个到底锁的是什么就不会出错了!

synchronized(Demo.class){

}
synchronized(this){

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值