Java 多线程之8锁现象---[观看bilibili-狂神说Java--学习笔记]

场景1

package com.zj970.lock;

/**
 * 标准情况下 是先sendEmail()还是callPhone()?
 * 答案: sendEmail()
 * 解释: 被synchronized 修饰的方式,锁的对象是方法的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 *
 * @auther zj970
 * @create 2023-04-10 下午4:04
 */
public class LockDemo1 {
    public static void main(String[] args) {
        Phone1 phone = new Phone1();

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

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

class Phone1 {
    public synchronized void sendEmail() { System.out.println(Thread.currentThread().getName() + "--->sendEmail");}

    public synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}

场景2

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * sendEmail()休眠3秒后 是先执行sendEmail()还是callPhone()
 * 答案:sendEmail()
 * 解释:被synchronized修饰的方式,锁的对象是方式的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 * @auther zj970
 * @create 2023-04-10 下午4:15
 */
public class LockDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone = new Phone2();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone.callOPhone();
        }, "B").start();
    }
}

class Phone2 {
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}

场景3

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized修饰的方法和普通方法 先执行sendEmail()还是callPhone()
 * 答案:callPhone()
 * 解释:新增加的这个方法没有synchronized修饰,不是同步方法,不受锁的影响!
 *
 * @auther zj970
 * @create 2023-04-10 下午4:22
 */
public class LockDemo3 {
    public static void main(String[] args) throws InterruptedException {
        Phone3 phone = new Phone3();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone.callOPhone();
        }, "B").start();
    }
}

class Phone3 {
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    //没有synchronized、static就是普通方式
    public void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}


场景4

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的不同方法?new两个实例 先执行sendEmail()还是callPhone()
 * 答案:先执行callPhone()
 * 解释:被synchronized修饰的不同方法,锁的对象是调用者也就是实例对象
 * 这里锁的是不同的调用者,所以互不影响
 * @auther zj970
 * @create 2023-04-10 下午4:29
 */
public class LockDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Phone4 phone = new Phone4();
        Phone4 phone1 = new Phone4();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone1.callOPhone();
        }, "B").start();
    }
}

class Phone4 {
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}


场景5

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 两个静态同步方法,都被synchronized修饰。先sendEmail()还是callPhone()?
 * 答案:sendEmail()
 * 解释: 只要方法被static修饰,锁的对象就是class模板对象,这个则全局唯一!
 * 所以说这里是同一个锁,并不是因为synchronized这里程序会从上往下依次执行
 * @auther zj970
 * @create 2023-04-10 下午4:40
 */
public class LockDemo5 {
    public static void main(String[] args) throws InterruptedException {
        Phone5 phone = new Phone5();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone.callOPhone();
        }, "B").start();
    }
}

class Phone5 {
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public static synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}


场景6

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized修饰的普通方法和静态方法 是先sendEmail()还是callPhone()?
 * 答案:callPhone()
 * 解释:只要被static修饰锁的是class模板,而synchronized锁的是调用的对像
 * 这两个锁互不影响,按时间先后执行
 * @auther zj970
 * @create 2023-04-10 下午5:07
 */
public class LockDemo6 {
    public static void main(String[] args) throws InterruptedException {
        Phone6 phone = new Phone6();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone.callOPhone();
        }, "B").start();
    }
}

class Phone6 {
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}

场景7

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 同被static+synchronized修饰的两个方法(两个实例对象),是先sendEmail()还是callPhone()?
 * 答案:sendEmail
 * 解释:只要方法被static修饰,锁的对象就是class模板对象,这个则全局唯一
 * 所以说这里是同一个锁,并不是因为synchronized
 * @auther zj970
 * @create 2023-04-10 下午5:19
 */
public class LockDemo7{
    public static void main(String[] args) throws InterruptedException {
        Phone7 phoneA = new Phone7();
        Phone7 phoneB = new Phone7();

        new Thread(() -> {
            try {
                phoneA.sendEmail();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }, "A").start();

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phoneB.callOPhone();
        }, "B").start();
    }
}

class Phone7 {
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public static synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}

场景8

package com.zj970.lock;

import java.util.concurrent.TimeUnit;

/**
 * 一个被static+synchronized修饰的方法和普通的synchronized方法,先执行sendEmail还是callPhone?
 * 答案:callPhone()
 * 解释:只要被static修饰的锁就是整个class模板
 * 这里一个锁的是class模板,一个锁的是拥有者
 * 所以锁的是两个对象,互不影响
 *
 * @auther zj970
 * @create 2023-04-10 下午5:40
 */
public class LockDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Phone8 phone = new Phone8();
        Phone8 phone1 = new Phone8();

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

        TimeUnit.SECONDS.sleep(2);
        new Thread(() -> {
            phone1.callOPhone();
        }, "B").start();
    }
}

class Phone8 {
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println(Thread.currentThread().getName() + "--->sendEmail");
    }

    public synchronized void callOPhone() {
        System.out.println(Thread.currentThread().getName() + "--->callPhone");
    }
}

总结

  只要分析锁的对象是那个就可以,staic + synchronized 锁的class全局唯一模板。单独synchronized修饰锁的是调用者(也就是实例化出来的对象,这个不唯一),调用者是同一对象,则按照锁的流程走。没有修饰的不受锁的影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhoujian970

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值