系列七、线程8锁

news/2024/5/20 6:37:30 标签: JUC

一、锁一

1.1、资源类Phone1

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone1 {

    /**
     * 发短信
     */
    public synchronized void sendMessage() {
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

1.2、线程类Lock8Demo1

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:标准访问,先打印短信还是先打印邮件
 */
public class Lock8Demo1 {

    public static void main(String[] args) throws InterruptedException {
        Phone1 phone1 = new Phone1();

        new Thread(() -> {
            try {
                phone1.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

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

}

1.3、分析

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

二、锁二

2.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone2 {

    /**
     * 发短信
     */
    public synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

2.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 */
public class Lock8Demo2 {

    public static void main(String[] args) throws InterruptedException {
        Phone2 phone2 = new Phone2();
        System.out.println(Thread.currentThread().getName());
        new Thread(() -> {
            try {
                phone2.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone2.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

2.3、分析

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

三、锁三

3.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone3 {

    /**
     * 发短信
     */
    public synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

    /**
     * 打招呼
     */
    public void sayHello() {
        System.out.println("===============>sayHello");
    }

}

3.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 */
public class Lock8Demo3 {

    public static void main(String[] args) throws InterruptedException {
        Phone3 phone3 = new Phone3();
        System.out.println(Thread.currentThread().getName());
        new Thread(() -> {
            try {
                phone3.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone3.sayHello();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

3.3、分析

普通方法和同步锁没有关系。

四、锁四

4.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone4 {

    /**
     * 发短信
     */
    public synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

4.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 *      4、现在有两部手机,先打印短信还是邮件
 */
public class Lock8Demo4 {

    public static void main(String[] args) throws InterruptedException {
        Phone4 phone1 = new Phone4();
        Phone4 phone2 = new Phone4();
        System.out.println(Thread.currentThread().getName());
        new Thread(() -> {
            try {
                phone1.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone2.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

4.3、分析

phone1和phone2锁的是2把不同的锁。

五、锁五

5.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone5 {

    /**
     * 发短信
     */
    public static synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public static synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

5.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 *      4、现在有两部手机,先打印短信还是邮件
 *      5、两个静态同步方法,1部手机,先打印短信还是邮件
 */
public class Lock8Demo5 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Phone5 phone1 = new Phone5();
        new Thread(() -> {
            try {
                phone1.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

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

}

5.3、分析

所有的静态同步方法用的是同一把锁,即类对象本身。

六、锁六

6.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone6 {

    /**
     * 发短信
     */
    public static synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public static synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

6.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 *      4、现在有两部手机,先打印短信还是邮件
 *      5、两个静态同步方法,1部手机,先打印短信还是邮件
 *      6、两个静态同步方法,2部手机,先打印短信还是邮件
 */
public class Lock8Demo6 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Phone6 phone1 = new Phone6();
        Phone6 phone2 = new Phone6();
        new Thread(() -> {
            try {
                phone1.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone2.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

6.3、分析

所有的静态同步方法用的是同一把锁,即类对象本身。

七、锁七

7.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone7 {

    /**
     * 发短信
     */
    public static synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

7.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 *      4、现在有两部手机,先打印短信还是邮件
 *      5、两个静态同步方法,1部手机,先打印短信还是邮件
 *      6、两个静态同步方法,2部手机,先打印短信还是邮件
 *      7、一个静态同步方法,一个普通同步方法,1部手机,先打印短信还是邮件
 */
public class Lock8Demo7 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Phone7 phone7 = new Phone7();
        new Thread(() -> {
            try {
                phone7.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone7.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

7.3、分析

sendMessage锁的是类对象本身,sendEmail锁的是当前对象本身,两者锁的不是同一个对象,所以不会存在竞争条件。

八、锁八

8.1、资源类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:03
 * @Description: 资源类
 */
public class Phone8 {

    /**
     * 发短信
     */
    public static synchronized void sendMessage() {
        // 线程休眠(单位:秒)
        try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
        System.out.println("===============>sendMessage");
    }

    /**
     * 发邮件
     */
    public synchronized void sendEmail() {
        System.out.println("===============>sendEmail");
    }

}

8.2、线程类

/**
 * @Author : 一叶浮萍归大海
 * @Date: 2023/11/20 14:06
 * @Description: 线程8锁
 * 问题:
 *      1、标准访问,先打印短信还是先打印邮件
 *      2、短信停4秒,先打印短信还是打印邮件
 *      3、新增普通的hello方法,是先打短信还是hello
 *      4、现在有两部手机,先打印短信还是邮件
 *      5、两个静态同步方法,1部手机,先打印短信还是邮件
 *      6、两个静态同步方法,2部手机,先打印短信还是邮件
 *      7、一个静态同步方法,一个普通同步方法,1部手机,先打印短信还是邮件
 *      8、一个静态同步方法,一个普通同步方法,2部手机,先打印短信还是邮件
 */
public class Lock8Demo8 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName());
        Phone8 phone1 = new Phone8();
        Phone8 phone2 = new Phone8();
        new Thread(() -> {
            try {
                phone1.sendMessage();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "AA").start();

        Thread.sleep(100);

        new Thread(() -> {
            try {
                phone2.sendEmail();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "BB").start();
    }

}

8.3、分析

sendMessage锁的是类对象本身,sendEmail锁的是当前对象本身,两者锁的不是同一个对象,所以不会存在竞争条件。

九、总结

synchronized实现同步的基础:Java中的每一个对象都可以作为锁


具体表现为以下3种形式。
        对于普通同步方法,锁是当前实例对象。
        对于静态同步方法,锁是当前类的Class对象。
        对于同步方法块,锁是synchonized括号里配置的对象

        当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!


http://www.niftyadmin.cn/n/5197099.html

相关文章

OpenHarmony Ohpm安装历程(个人踩坑,最后安装成功)

大家好,我是【八戒,你又涨价了哎】 以下是我个人在学习OpenHarmony过程中的分享,请大家多多指教 目录 问题描述: 尝试解决 尝试一、 尝试二、 尝试三、 最终解决方案 问题描述: 当我学习到使用OpenHarmony的三方…

比特位计算

比特位计算 描述 : 给你一个整数 n &#xff0c;对于 0 < i < n 中的每个 i &#xff0c;计算其二进制表示中 1 的个数 &#xff0c;返回一个长度为 n 1 的数组 ans 作为答案。 题目 : LeetCode 335.比特位计算 : 338. 比特位计数 分析 : 这个题目跟上面的题目很像…

Java vo dto 使用场景

在Java中&#xff0c;VO&#xff08;Value Object&#xff09;和DTO&#xff08;Data Transfer Object&#xff09;是常用的设计模式&#xff0c;用于数据传递和封装。它们分别适用于不同的场景&#xff1a; VO&#xff08;Value Object&#xff09;&#xff1a;用于表示具有一…

Android Termux安装MySQL,内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…

【Kingbase FlySync】命令模式:部署双轨并行,并实现切换同步

【Kingbase FlySync】命令模式:安装部署同步软件&#xff0c;实现Oracle到KES实现同步 双轨并行方案说明一.准备工作二.环境说明三.目标实操(1).准备安装环境Orcle服务器(Oracle40)1.上传所有工具包2.操作系统配置a.增加flysync 用户、设置密码b.配置环境变量c.调整limits.conf…

【23真题】超难985!做完感觉没学过!

本套试卷难度分析&#xff1a;22年西北工业大学827考研真题&#xff0c;我也发布过&#xff0c;若有需要&#xff0c;戳这里自取&#xff01;本套试题内容有难度&#xff0c;题目考察全为大题&#xff0c;题目不多&#xff01;但是题目都很新颖&#xff0c;状态方程的题目考察较…

删除 word 中嵌入文字下方的图片

问题&#xff1a;Word中插入图片&#xff0c;选择图片格式【衬于文字下方】后&#xff0c;无法选择图片并删除。 解决方法&#xff1a; 如图所示&#xff0c;选择 【开始】-【编辑】-【选择】-【选择对象】&#xff0c;然后鼠标放在图片位置即可选中图片进行删除操作。

RecyclerView嵌套布局,导致RecyclerView复用失效 解决

前言&#xff1a;使用NestedScrollView嵌套RecyclerView。 解决步骤一&#xff1a;固定高度 NestedScrollView嵌套RecyclerView时&#xff0c;RecyclerView的高度是无限大&#xff0c;所以要将RecyclerView设置固定高度。在代码中固定的&#xff0c;灵活度更高。 binding.nest…