IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Java实现经典八锁问题 -> 正文阅读

[Java知识库]Java实现经典八锁问题

🚀在 Loki的个人博客,阅读体验更佳

下面将通过经典的8锁问题,认清锁原理

场景一

import java.util.concurrent.TimeUnit;

/**
 * 标准情况下 是先sendEmail() 还是先callPhone()?
 * 答案:sendEmail
 * 解释:被 synchronized 修饰的方式,锁的对象是方法的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 */
public class LockDemo1 {
    public static void main(String[] args) throws InterruptedException {
        Phone1 phone1 = new Phone1();
        new Thread(()->{
            phone1.sendEmail();
        },"A").start();
        TimeUnit.SECONDS.sleep(3);
        new Thread(()->{
            phone1.callPhone();
        },"B").start();
    }
}
class Phone1{
    public synchronized void sendEmail(){
        System.out.println("senEmail");
    }
    public synchronized  void callPhone(){
        System.out.println("callPhone");
    }
}

场景二

import java.util.concurrent.TimeUnit;

/**
 * sendEmail()休眠三秒后  是先执行sendEmail() 还是 callPhone()
 * 答案: sendEmail
 * 解释:被 synchronized 修饰的方式,锁的对象是方法的调用者
 * 所以说这里两个方法调用的对象是同一个,先调用的先执行!
 */
public class LockDemo2 {
    public static void main(String[] args) throws InterruptedException {
        Phone2 phone2 = new Phone2();
        new Thread(()->{
            try {
                phone2.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();
        TimeUnit.SECONDS.sleep(2); // 休眠2秒
        new Thread(()->{
            phone2.callPhone();
        },"B").start();
    }
}
class Phone2{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }
    public synchronized void callPhone(){
        System.out.println("callPhone");
    }
}

场景三

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的方式和普通方法 先执行sendEmail() 还是 callPhone()
 * 答案: callPhone
 * 解释:新增加的这个方法没有 synchronized 修饰,不是同步方法,不受锁的影响!
 */
public class LockDemo3 {
    public static void main(String[] args) throws InterruptedException {
        Phone3 phone3 = new Phone3();
        new Thread(()->{
            try {
                phone3.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(2);
        new Thread(()->{
            phone3.callPhone();
        },"B").start();
    }
}
class Phone3{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(4);
        System.out.println("sendEmail");
    }

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

场景四

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的不同方法 先执行sendEmail() 还是callPhone()?
 * 答案:callPhone
 * 解释:被synchronized 修饰的不同方法 锁的对象是调用者
 * 这里锁的是两个不同的调用者,所有互不影响
 */
public class LockDemo4 {
    public static void main(String[] args) throws InterruptedException {
        Phone4 phoneA = new Phone4();
        Phone4 phoneB = new Phone4();

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

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone4{
    public synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }
    public synchronized void callPhone(){
        System.out.println("callPhone");
    }
}

场景五

import java.util.concurrent.TimeUnit;

/**
 * 两个静态同步方法 都被synchronized 修饰 是先sendEmail() 还是callPhone()?
 * 答案:sendEmial
 * 解释:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!
 *      所以说这里是同一个锁,并不是因为synchronized  这里程序会从上往下依次执行
 */
public class LockDemo5 {
    public static void main(String[] args) throws InterruptedException {
        Phone5 phone5 = new Phone5();
        new Thread(()->{
            try {
                phone5.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phone5.callPhone();
        },"B").start();
    }
}
class Phone5{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

场景六

import java.util.concurrent.TimeUnit;

/**
 * 被synchronized 修饰的普通方法和静态方法  是先sendEmail() 还是 callPhone()?
 * 答案:callPhone
 * 解释:只要被static修饰锁的是class模板, 而synchronized 锁的是调用的对象
 * 这里是两个锁互不影响,按时间先后执行
 */
public class LockDemo6 {
    public static void main(String[] args) throws InterruptedException {
        Phone6 phone6 = new Phone6();
        new Thread(()->{
            try {
                phone6.sendEmail();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phone6.callPhone();
        },"B").start();
    }
}
class Phone6{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

场景七

import java.util.concurrent.TimeUnit;

/**
 * 同被static+synchronized 修饰的两个方法,是先sendEmail()还是callPhone()?
 *  答案:sendEmail
 *  解释:只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一
 *  所以说这里是同一个锁,并不是因为synchronized
 */
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) {
                e.printStackTrace();
            }
        },"A").start();

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone7{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

场景八

import java.util.concurrent.TimeUnit;

/**
 * 一个被static+synchronized 修饰的方法和普通的synchronized方法,先执行sendEmail()还是callPhone()?
 * 答案:callPhone()
 * 解释: 只要被static 修饰的锁的就是整个class模板
 * 这里一个锁的是class模板 一个锁的是调用者 
 * 所以锁的是两个对象 互不影响
 */
public class LockDemo8 {
    public static void main(String[] args) throws InterruptedException {
        Phone8 phoneA = new Phone8();
        Phone8 phoneB = new Phone8();

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

        TimeUnit.SECONDS.sleep(1);
        new Thread(()->{
            phoneB.callPhone();
        },"B").start();
    }
}
class Phone8{
    public static synchronized void sendEmail() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        System.out.println("sendEmail");
    }

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

小结:

synchronized(Demo.class){

}
synchronized(this){

}

1、new this 调用的是这个对象,是一个具体的对象!
2、static class 唯一的一个模板!

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

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-09 12:26:14  更:2022-05-09 12:26:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:11:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码