线程的同步机制

2023-05-16

方式一:同步代码块

synchronized(同步监视器){
	//需要被同步的代码
}

说明:1.操作共享数据的代码就是需要被同步的代码。
2.共享数据:多个线程共同操作的变量。比如:ticket就是共享数据
3.同步监视器,俗称锁。任何一个类的对象都可以充当锁。
要求:多个线程必须共用同一把锁。
补充:在实现Runnable接口创建多线程的方式中,我们可以考虑使用this充当同步监视器。

方式二:同步方法

如果操作共享数据的代码完整的声明在一个方法中,我们不妨将此方法声明为同步的。
关于同步方法的总结:
1.同步方法仍然涉及同步监视器,只是不需要我们显式的声明。
2.非静态的同步方法,同步监视器是:this
静态的同步方法,同步监视器是:当前类本 身。(类名.class)

代码演示

/**
 * @Date:CreatedIn 2020/6/8 21:38
 * @Description: 线程的安全问题(有共享数据的时候才会出现线程安全问题即多个线程处理同一部分数据)
 * 采用锁(同步监视器)
 * 同步监视器(锁)的要求:
 * 任意类的对象都可以作为锁,但是必须所有进程共用同一个锁
 */
public class Tickets {
    public static void main(String[] args) {
        Windows windows = new Windows();
        Thread thread1 = new Thread(windows);
        Thread thread2 = new Thread(windows);
        Thread thread3 = new Thread(windows);
        thread1.setName("窗口1:");
        thread2.setName("窗口2:");
        thread3.setName("窗口3:");
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

class Windows implements Runnable {
    private int tickets = 100;

    @Override
    public void run() {

        //优缺点:在这个同步机制外面 ,多线程同步进行;
        //      到了这里,虽然安全的问题接菌了,但是相当于多线程变单线程了。。。。效率变慢
        //当要处理的部分害怕各线程之间由于抢占cpu造成的线程不安全问题
        //加上锁之后,当一个线程已经进来这个区域,哪怕发生了阻塞,别的线程也
        //会继续在外面等着这个线程结束以后才能进来执行
        while (true) {
            synchronized (Windows.class) { //此处便为锁
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖出了:" + (tickets--));
                }else{
                    break;
                }
            }
        }
    }
}

方式三:Lock锁 — JDK5.0新增

synchronized与Lock的异同?
相同点:二者都可以解决线程的安全问题
不同点:synchronized机制在执行完相应的同步代码后,自动释放同步监视器;
Lock需要手动的启动同步(lock()),同时结束同步也需手动结束(unlock())

代码演示

import java.util.concurrent.locks.ReentrantLock;

/**
 * @Date:CreatedIn 2020/6/9 13:13
 * @Description: 解决线程安全的第三种方法,JDK5.0以后新增的。
 * ReentrantLock使用lock()方法
 */
public class Tickets1 {

    public static void main(String[] args) {
        Windows1 windows1 = new Windows1();
        Thread thread1 = new Thread(windows1);
        Thread thread2 = new Thread(windows1);
        Thread thread3 = new Thread(windows1);
        thread1.start();
        thread2.start();
        thread3.start();

    }
}

class Windows1 implements Runnable{
private int tickets = 100;
private ReentrantLock lock = new ReentrantLock();//构造器如果选择true的话,说明各线程公平执行
                                                //谁先进来谁先执行,不填或者false的话各线程抢占。
    @Override
    public void run() {

        while (true) {
            try {
                lock.lock();//上锁
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + "卖票:" + (tickets--));
                } else {
                    break;
                }
            } finally {
                lock.unlock();//解锁
            }
        }
    }
}

补充

同步的利弊分析

优点:同步的方式解决了线程的安全问题。
缺点:操作同步代码时,只有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。

死锁的理解

不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了死锁。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

线程的同步机制 的相关文章

  • MySQL常见七种通用的Join查询练习题

    准备数据库表 t dept 和 t emp CREATE TABLE 96 t dept 96 96 id 96 int NOT NULL AUTO INCREMENT 96 deptName 96 varchar 30 DEFAULT N
  • MySQL索引分类

    主键索引 xff1a 设定为主键后数据库会自动建立索引 xff0c innodb为聚簇索引 单值索引 xff1a 即一个索引只包含单个列 xff0c 一个表可以有多个单列索引 唯一索引 xff1a 索引列的值必须唯一 xff0c 但允许有空
  • Docker 部署 MySQL 一主多从

    主从复制的原理 xff1a 1 主库 xff1a 创建一个有权访问binlog日志的从库账号 xff0c 配置需要主从复制的库 有写操作时 xff0c 可以将写操作或者写操作之后的数据记录到日志文件中 binlog 通过一个线程通知需要同步
  • Java笔记(8)——重载(Overload)与重写(Override)的区别

    1 重写 xff08 Override xff09 重写是子类对允许访问的父类的方法进行重新编写的过程 xff0c 方法名 返回值和参数列表不能变 xff0c 方法中的内容可以变化 特点就是 xff1a 子类可以根据自己的需要对父类的方法进
  • ShardingSphere介绍

    官网 xff1a https shardingsphere apache org index zh html 文档 xff1a https shardingsphere apache org document 5 1 1 cn overvi
  • ShardingSphere-JDBC读写分离

    基于之前搭建的mysql主从读写分离使用ShardingSphere JDBC实现读写分离 参考文章 xff1a Docker 部署 MySQL 一主多从 书启秋枫的博客 CSDN博客 CREATE DATABASE mydb2 USE m
  • ShardingSphere-JDBC垂直分片

    什么是数据分片 xff1f 简单来说 xff0c 就是指通过某种特定的条件 xff0c 将我们存放在同一个数据库中的数据分散存放到多个数据库 xff08 主机 xff09 上面 xff0c 以达到分散单台设备负载的效果 数据的切分 xff0
  • ShardingSphere-JDBC水平分片

    项目中可以使用ShardingSphere JDBC将数据存到不同库的表中 一 准备服务器 服务器规划 xff1a 使用docker方式创建如下容器 主服务器 xff1a 容器名server order0 xff0c 端口3310从服务器
  • ShardingSphere-JDBC绑定表

    一 什么是绑定表 指分片规则一致的一组分片表 使用绑定表进行多表关联查询时 xff0c 必须使用分片键进行关联 xff0c 否则会出现笛卡尔积关联或跨库关联 xff0c 从而影响查询效率 例如 xff1a t order 表和 t orde
  • ShardingSphere-JDBC广播表

    一 什么是广播表 指所有的分片数据源中都存在的表 xff0c 表结构及其数据在每个数据库中均完全一致 适用于数据量不大且需要与海量数据的表进行关联查询的场景 xff0c 例如 xff1a 字典表 广播具有以下特性 xff1a xff08 1
  • 01_JUC概述

    1 JUC是什么 xff1f 在 Java 5 0 提供了 java util concurrent 简称JUC 包 xff0c 在此包中增加了在并发编程中很常用的工具类 此包包括了几个小的 已标准化的可扩展框架 xff0c 并提供一些功能
  • 02_Lock锁

    首先看一下JUC的重磅武器 锁 xff08 Lock xff09 相比同步锁 xff0c JUC包中的Lock锁的功能更加强大 xff0c 它提供了各种各样的锁 xff08 公平锁 xff0c 非公平锁 xff0c 共享锁 xff0c 独占
  • 03_线程间通信

    面试题 xff1a 两个线程打印 两个线程 xff0c 一个线程打印1 52 xff0c 另一个打印字母A Z打印顺序为12A34B 5152Z xff0c 要求用线程间通信 public class Demo01 public stati
  • 04_并发容器类

    1 重现线程不安全 xff1a List 首先以List作为演示对象 xff0c 创建多个线程对List接口的常用实现类ArrayList进行add操作 public class NotSafeDemo public static void
  • Java笔记(10)——异常处理

    1 Java异常 Java运行时发生异常可以分为两类 xff1a Error xff1a JVM系统内部错误 资源耗尽等问题产生的异常 Exception xff1a 编程错误或偶然的外在因素导致的 2 常见的异常 2 1 RuntimeE
  • mariadb 数据库连接使用

    今天测试了使用mariadb的使用 xff0c 我使用的springboot 43 mariadb 来操作数据库 xff0c 和以前的代码基本一样 xff0c 就数据变成了mariadb xff0c 驱动还是使用mysql的 pom 文件如
  • 05_JUC强大的辅助类

    JUC的多线程辅助类非常多 xff0c 这里我们介绍三个 xff1a CountDownLatch xff08 倒计数器 xff09 CyclicBarrier xff08 循环栅栏 xff09 Semaphore xff08 信号量 xf
  • 06_Callable接口

    Thread 类 Runnable 接口使得多线程编程简单直接 但Thread类和Runnable接口都不允许声明检查型异常 xff0c 也不能定义返回值 没有返回值这点稍微有点麻烦 不能声明抛出检查型异常则更麻烦一些 public voi
  • 07_阻塞队列(BlockingQueue)

    目录 1 什么是BlockingQueue 2 认识BlockingQueue 3 代码演示 栈与队列概念 栈 Stack xff1a 先进后出 xff0c 后进先出 队列 xff1a 先进先出 1 什么是BlockingQueue 在多线
  • 08_ThreadPool线程池

    1 架构说明 Java中的线程池是通过Executor框架实现的 xff0c 该框架中用到了Executor xff0c ExecutorService xff0c ThreadPoolExecutor这几个类 Executor接口是顶层接

随机推荐

  • Docker 安装 elasticsearch、kibana、ik

    一 安装elasticsearch 1 拉取 elasticsearch 镜像 docker pull elasticsearch 7 6 2 2 创建 elasticsearch 容器 docker run name elasticsea
  • ElasticSearch 中 FieldType 详解

    date float long都是不能够被拆分的 64 Field type 61 FieldType Text analyzer 61 34 ik max word 34 表示该字段是一个文本 xff0c 并作最大程度拆分 xff0c 默
  • SpringBoot 使用 ElasticSearch 编程测试

    1 在 pom xml 准备依赖 lt dependency gt lt groupId gt org projectlombok lt groupId gt lt artifactId gt lombok lt artifactId gt
  • el-table-column中formatter格式化字典

    el table column中formatter格式化字典 vue 中使用 lt el table column gt 中的 formatter 格式化内容 x1f52e lt template gt lt 列表 gt lt el tab
  • cookie和session详解

    源自 xff1a https www cnblogs com l199616j p 11195667 html xff0c 有删减 另 xff0c cookie session与token的真正区别 xff1a https blog csd
  • 如何理解端到端

    1 非端到端 xff1a 典型的自然语言处理 xff08 Natural Language Processing xff09 过程 xff1a 分词 gt 词性标注 gt 句法分析 gt 语义分析 直至得出结果 多个独立步骤 xff0c 每
  • Java笔记(11)——Collection集合

    0 先创建一个Person类为例 span class token keyword public span span class token keyword class span span class token class name Pe
  • 笔记:QGC使用及姿态环仿真调节方式

    笔记 xff1a QGC使用及姿态环仿真调节方式 打开Gazebo及QGC 进入终端管理员权限 sudo s 在终端打开Gazebo cd Firmware make px4 sitl default gazebo 点击文件夹中的QGC x
  • springboot集成freemarker模板,项目打成jar包到生产环境显示找不到模板文件

    文章目录 一 问题描述二 原始代码三 解决方案四 注意点 一 问题描述 1 使用springboot集成freemarker模版后 xff0c 在本地运行正常 xff1b 打成jar包后到线上测试报如下错误 xff1a 2 原因 xff1a
  • Linux网络设置

    文章目录 引言一 查看网络配置1 查看网络接口信息ifconfig2 修改网络配置文件3 设置网络接口参数 二 主机名称配置文件hostname1 hostname命令2 三种修改主机名的方式2 1 临时修改主机名 xff08 hostna
  • Java中的集合类

    Java中所有的类都位于java util包下 xff0c 主要由两个接口派生出来 分别是Collection xff08 集合 xff09 和Map Collection xff08 映射集合 xff09 xff0c 包含了List和Se
  • 退出VM VirtualBox独占的键盘和鼠标

    今天无意之间点了菜单栏的 热键 鼠标集成 xff0c 结果鼠标被锁在了里面出不来 xff0c 试了好多方法都不行 xff0c 有点奔溃 xff0c 最后发现 右边的Alt 43 Ctrl组合键可以跳出
  • Linux - 第11节 - 网络入门

    目录 1 计算机网络背景 1 1 网络发展 1 2 认识 34 协议 34 2 网络协议初识 2 1 协议分层 2 2 OSI七层模型 2 3 TCP IP五层 xff08 或四层 xff09 模型 3 网络传输基本流程 3 1 同局域网的
  • @PathVariable注解的用法和作用

    64 PathVariable注解的用法和作用 64 PathVariable 映射 URL 绑定的占位符 通过 64 PathVariable 可以将 URL 中占位符参数绑定到控制器处理方法的入参中 URL 中的 xxx 占位符可以通过
  • 最新虚拟机中Ubuntu18.04安装教程(傻瓜教程)

    1 文件和软件下载 下载Ubuntu18 04文件 可以直接点下方的链接下载 Ubuntu18 04安装链接 下载VMware Workstation 笔者这边使用的是VMware Workstation15 5pro xff0c 大家也可
  • optimizer优化器详解

    在机器学习中 xff0c 优化器 xff08 optimizer xff09 是一种用于更新模型参数以最小化训练误差的算法 它可以将损失函数的梯度作为输入 xff0c 并根据该梯度调整模型参数的值 常见的优化器算法包括随机梯度下降 xff0
  • Java创建多线程的四种方式

    一 继承Thread类 1 创建一个继承于Thread类的子类 2 重写Thread类的run gt 将此线程执行的操作声明在run 中 3 创建Thread类的子类的对象 4 通过此对象调用start 启动当前线程 调用当前线程的run
  • MySQL基础

    本单元目标 一 为什么要学习数据库 二 数据库的相关概念 DBMS DB SQL 三 数据库存储数据的特点 四 初始MySQL MySQL产品的介绍 MySQL产品的安装 MySQL服务的启动和停止 MySQL服务的登录和退出 MySQL的
  • Thread类中的常用方法

    Thread类中的常用方法 xff08 学习总结 xff09 xff1a 序号函数作用1start 启动当前线程 xff1b 调用当前线程的run 2run 通常需要重写Thread类中的此方法 xff0c 将创建的线程要执行的操作生命在此
  • 线程的同步机制

    方式一 xff1a 同步代码块 span class token keyword synchronized span span class token punctuation span 同步监视器 span class token punc