JUC系列(二)八个有关锁的问题,让你吃透各种场景

简介: 8锁就是关于的锁的八个问题,下面也有四个demo类来阐述各种场景下锁的不同状态

在使用锁的时候一些有趣的问题

📣 📣 📣 📢📢📢
☀️☀️你好啊!小伙伴,我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。
📒 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️,擅长使用Java技术开发web项目和工具
📒 文章内容丰富:覆盖大部分java必学技术栈,前端,计算机基础,容器等方面的文章
📒 如果你也对Java感兴趣,关注小冷吧,一起探索Java技术的生态与进步,一起讨论Java技术的使用与学习
✏️高质量技术专栏专栏链接: 微服务数据结构netty单点登录SSMSpringCloudAlibaba
😝公众号😝想全栈的小冷,分享一些技术上的文章,以及解决问题的经验
当前专栏JUC系列

8锁现象

锁 ----> 刚new 出来的对象、class

8锁就是关于的锁的八个问题,下面也有四个demo类来阐述各种场景下锁的不同状态

demo1

两个问题:

正常模式下 在两个同步线程方法调用的时候 中途延时1s 会不会改变输出结果

答:不会影响输出顺序

正常模式下 同步方法内延时4s 会不会印象输出

答:不会影响输出顺序

  • 标准情况下 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
  • 发短信延时四秒 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话

demo代码

package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 * 1. 标准情况下 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
 * 2. 发短信延时四秒 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo {
    public static void main(String[] args) {
        phone phone = new phone();
        new Thread(() -> {
            phone.sendSms();
        }, "A").start();
        //    捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            phone.call();
        }, "B").start();
    }
}

class phone {
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

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

同步方法执行和普通方法执行顺序

答 :普通方法没有锁,所以普通方法先

两个对象执行会不会影响顺序

答:会 两个不同的对象锁也是不同的 ,对象1 还在等待,对象2调用的call方法不用等待所以先输出

  • 现在新增一个普通方法 问 先发短信还是先发hello 先输出hello
  • 新增两个对象 是先打电话还是先发短信
package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 * 3、 现在新增一个普通方法  问 先发短信还是先发hello 先输出hello
 * 4、 新增两个对象 是先打电话还是先发短信
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo2 {
    public static void main(String[] args) {
        //两个对象,现在是两个调用者所以是两个锁
        phone2 phone = new phone2();
        phone2 phone1 = new phone2();
        new Thread(() -> {
            phone.sendSms();
        }, "A").start();
        //    捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            phone1.call();
        }, "B").start();
    }
}

class phone2 {
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    public synchronized void sendSms() {
        try {
            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");
    }
}
demo3

一个对象调用静态同步方法会不会改动执行顺序

答: 不会 ,static是锁的类模版全局唯一,不会改变锁的执行交换顺序

两个对象调用静态同步方法会不会改变执行顺序

答:不会 static修饰的是类模版,锁的也是类模板而不是类对象,只要是这个类生成的对象,不管多少个都不会改变顺序

  • 一个对象 添加两个静态的同步方法,只有一个对象 先打印 发短信 还是打电话?
  • 添加两个对象,分别调用静态同步方法 先打印 发短信 还是打电话?
package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 *  5、添加两个静态的同步方法,只有一个对象 先打印 发短信 还是打电话?
 *  6、 添加两个对象,增加两个同步方法 先打印  发短信 还是打电话?
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo3 {
    public static void main(String[] args) {

        //不管多少对象, 使用的都是底层的唯一class所以不管怎么怎么改变结果都不会变,
        // 因为synchroized锁的是class对象,static修饰的方法 类一开始就加载了,
        new Thread(() -> {
            Phone3.sendSms();
        }, "A").start();
        //    捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            Phone3.call();
        }, "B").start();
    }
}

//phone3是唯一的一个class
class Phone3 {
    //synchronized 锁的对象是方法调用者,
    //两个方法用的都是 phone 对象的锁,两个方法谁先拿到锁 谁执行
    // 这里 static 是静态方法 ,类一加载就有了,这个用的锁不再是 phone锁 而是class锁
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

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

}
demo4
  • 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,因为锁的不是一个东西,sync锁的是类,static 是锁class
  • 两个对象 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,

答: 不是同一个锁,谁执行快就输出谁,

package lock8;

import java.util.concurrent.TimeUnit;

/**
 * @projectName: JUC
 * @package: Lock8
 * @className: lock8Demo
 * @author: 冷环渊 doomwatcher
 * @description: TODO
 *  Lock8 就是关于锁的八个问题
 *  7、一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,因为锁的不是一个东西,sync锁的是类,static 是锁class
 *  8、两个对象 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,
 * @date: 2022/3/2 1:13
 * @version: 1.0
 */
public class lock8Demo4 {
    public static void main(String[] args) {
        Phone4 phone = new Phone4();
        //不管多少对象, 使用的都是底层的唯一class所以不管怎么怎么改变结果都不会变,
        // 因为synchroized锁的是class对象,static修饰的方法 类一开始就加载了,
        new Thread(() -> {
            Phone4.sendSms();
        }, "A").start();
        //    捕获
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            phone.call();
        }, "B").start();
    }
}

//phone3是唯一的一个class
class Phone4 {
    //静态同步方法是锁的 class
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(4);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    //这里普通同步方法锁的是 phone
    public synchronized void call() {
        System.out.println("打电话");
    }

}
小结

我们通过八种不同的情况来理解锁在不同情况下的执行情况:

  • 标准情况下 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
  • 发短信延时四秒 两个线程打印 发短信还是打电话 1/ 发短信 2/打电话
  • 现在新增一个普通方法 问 先发短信还是先发hello 先输出hello
  • 新增两个对象 是先打电话还是先发短信
  • 一个对象 添加两个静态的同步方法,只有一个对象 先打印 发短信 还是打电话?
  • 添加两个对象,分别调用静态同步方法 先打印 发短信 还是打电话?
  • 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,因为锁的不是一个东西,sync锁的是类,static 是锁class
  • 两个对象 一个静态方法和一个普通加锁方法, 先打印 发短信 还是打电话? 先出打电话,

大家可以自己写一下代码看一些这些问题的结果,实践出效果,实践出理解

锁的东西,无非就是对象和 类模版

  1. new 出来的对象 就是锁具体的对象,比如普通同步方法
  2. 带有static 修饰的静态同步方法 锁的是类模版是全局唯一的对象class如 : class
相关文章
|
4月前
|
Java
【多线程面试题二十二】、 说说你对读写锁的了解
这篇文章讨论了读写锁(ReadWriteLock)的概念和应用场景,强调了读写锁适用于读操作远多于写操作的情况,并介绍了Java中`ReentrantReadWriteLock`实现的读写锁特性,包括公平性选择、可重入和可降级。
|
7月前
|
安全 Java 数据安全/隐私保护
剑指JUC原理-16.读写锁(下)
剑指JUC原理-16.读写锁
41 0
|
7月前
|
缓存 数据库 容器
剑指JUC原理-16.读写锁(上)
剑指JUC原理-16.读写锁
74 0
|
设计模式 Java 容器
一篇神文就把java多线程,锁,JMM,JUC和高并发设计模式讲明白了
今天给大家分享一篇一线开发大牛整理的java高并发核心编程神仙文档,里面主要包含的知识点有:多线程、线程池、内置锁、JMM、CAS、JUC、高并发设计模式、Java异步回调、CompletableFuture类等。
|
设计模式 安全 Java
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我
|
SQL 安全 Java
Java并发编程面试题——JUC专题
Java并发编程面试题——JUC专题
426 0
|
安全 Java Linux
JUC (java并发编程学习分享篇)
JUC (java并发编程学习分享篇)
80 0
|
安全 Java
Java多线程进阶——JUC常见类和死锁
java中的JUC就是java.util.concurrent包下的一些标准类或者接口,这个包里的东西都是和多线程相关的,以下就是这个包中常见的类和接口的用法及示例:
171 0
Java多线程进阶——JUC常见类和死锁
|
安全 Java
92. 你说你精通Java并发,那给我讲讲JUC吧(二)
92. 你说你精通Java并发,那给我讲讲JUC吧(二)
96 1
|
Java 调度 数据库
面试官:谈一谈java中基于AQS的并发锁原理
面试官:谈一谈java中基于AQS的并发锁原理
111 0
面试官:谈一谈java中基于AQS的并发锁原理