Java关键词synchronized

目录

一、通过卖票系统观察多线程的安全隐患

二、synchronized的基本知识

1.使用synchronized的原因

2.synchronized的作用

3.synchronized的基本格式

  a.synchronized加在方法名前

  b.synchronized用在方法中

4. Java锁机制

5.synchronized注意事项

三、使用synchronized修改卖票系统代码


一、通过卖票系统观察多线程的安全隐患

public class Tickets {
    int num;

    public Tickets(int num) {
        this.num = num;
    }

    public int getNum() {
        return this.num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}
public interface TicketService {
    public void sale();
}
public class SaleTickets implements TicketService {
    private Tickets tickets;

    public SaleTickets() {

    }

    public SaleTickets(Tickets tickets) {
        this.tickets = tickets;
    }

    public void sale() {
        int num = tickets.getNum();
        System.out.println(Thread.currentThread().getName() + "正在出库第" + num + "张票,剩余" + --num + "张票");
        tickets.setNum(num);
    }
}
public class Window {
    public static void main(String[] args) {
        Tickets tickets = new Tickets(50);
        TicketService saleTickets = new SaleTickets(tickets);
        new Thread(() -> {
            while (tickets.getNum() > 0) {
                saleTickets.sale();
            }
        },"窗口1").start();
        new Thread(() -> {
            while (tickets.getNum() > 0) {
                saleTickets.sale();
            }
        },"窗口2").start();
    }
}

运行结果:

运行结果中出现重复出售票数的现象,因此需要了解synchronized关键词的操作来解决这一问题

二、synchronized的基本知识

1.使用synchronized的原因

        当多个线程共享一个数据时,如果处理不当,很容易出现线程的安全隐患,比如丢失修改、不可重复读、读脏数据等,所以多线程编程时经常要解决线程同步问题。

2.synchronized的作用

        当某个对象用synchronized修饰时,表明该对象在任何时刻都只能由一个线程访问。当一个线程进人synchronized方法后,能保证在任何其他线程访问这个方法之前完成自己的执行。如果一个线程试图访问一个已经启动的synchronized方法,则这个线程必须等待,直到已启动线程执行完毕,再释放这个synchronized方法。

3.synchronized的基本格式

  a.synchronized加在方法名前

 public synchronized void Method1() {// (访问权限修饰符+synchronized+返回值类型+方法名)
        /* 方法体 */
    }

  b.synchronized用在方法中

 public void Method2() {// (访问权限修饰符+返回值类型+方法名)
        synchronized (this) {
            /* 代码块 */
        }
    }

4. Java锁机制

        Java使用锁机制保证同步代码块或方法的“原子性”,即保持整体性,不可分隔。Java中每个对象都有一个内置锁,只有当对象具有同步代码时,内置锁才会起作用。当进人一个同步方法时,线程自动获得方法所在类的当前实例相关的锁,即给this对象加锁。当同步代码块或同步方法执行完毕后,同步对象上的锁就被解除,该线程就有机会获取该对象的锁。

5.synchronized注意事项

a.如果synchronized用在类声明中,则表明该类中的所有方法都是synchronized的。

b.锁不属于线程,而是属于对象,一个线程可以拥有多个对象的锁,而只有同一个对象之间的锁才会互斥。

三、使用synchronized修改卖票系统代码

        并发环境下,对每个请求创建了多个线程去处理。这段对统计变量操作的代码,曝露在多线程环境下,却没有任何同步处理,从而导致重复卖票问题。

public class Tickets {
    int num;

    public Tickets(int num) {
        this.num = num;
    }

    public int getNum() {
        return this.num;
    }

    public void setNum(int num) {
        this.num = num;
    }
}
public interface TicketService {
    public void sale();
}
public class SaleTickets implements TicketService {
    private Tickets tickets;

    public SaleTickets() {

    }

    public SaleTickets(Tickets tickets) {
        this.tickets = tickets;
    }

    public void sale() {
        synchronized (this) {
            int num = tickets.getNum();
            if (num > 0) {
                System.out.println(Thread.currentThread().getName() + "正在出库" + num + "张票,剩余" + --num + "张票");
                tickets.setNum(num);
            }
        }
    }
}
public class Window {
    public static void main(String[] args) {
        Tickets tickets = new Tickets(50);
        TicketService saleTickets = new SaleTickets(tickets);
        new Thread(() -> {
            while (tickets.getNum() > 0) {
                saleTickets.sale();
            }
        },"窗口1").start();
        new Thread(() -> {
            while (tickets.getNum() > 0) {
                saleTickets.sale();
            }
        },"窗口2").start();
    }
}

运行结果: 

 此时运行结果中没有出现重复出售票的现象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/29836.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java Logback日志框架概述及logback.xml详解

日志技术具备的优势 可以将系统执行的信息选择性的记录到指定的位置(控制台、文件中、数据库中)。 可以随时以开关的形式控制是否记录日志,无需修改源代码。 日志体系结构 Logback日志框架 Logback是由log4j创始人设计的另一个开源日志组件&#xff0…

MATLAB读取OpenFOAM的二进制文件

OpenFOAM的文件格式 上面是OpenFOAM二进制文件的格式,我们可以看出,前面21行都是无关的说明文件,22开始时除了一个括号之外,其它的都是数据。 读取数据 读取数据的思路非常简单,忽略不需要的,读取需要的。…

Autoware 跑 Demo(踩坑指南)

Autoware 跑 Demo(踩坑指南) 网上的博客和官方的教程,几乎都是一样的,但实际上跑不起来 Autoware 1.12学习整理–01–运行rosbag示例 Autoware入门学习(三)——Autoware软件功能使用介绍(1/3&a…

【Unity3D】激光雷达特效

1 由深度纹理重构世界坐标 屏幕深度和法线纹理简介中对深度和法线纹理的来源、使用及推导过程进行了讲解,本文将介绍使用深度纹理重构世界坐标的方法,并使用重构后的世界坐标模拟激光雷达特效。 本文完整资源见→Unity3D激光雷达特效。 1)重构…

基于51单片机的智能火灾报警系统温度烟雾光

wx供重浩:创享日记 对话框发送:火灾报警 获取完整源码源文件电路图仿真文件论文报告等 功能简介 51单片机MQ-2烟雾传感ADC0832模数转换芯片DS18B20温度传感器数码管显示按键模块声光报警模块 具体功能: 1、实时监测及显示温度值和烟雾浓度…

管理类联考——英语二——技巧篇——写作——B节——议论文——必备替换句型

议论文必备替换句型 (一)表示很明显/众所周知的句型 It is obvious thatIt is clear thatIt is apparent thatIt is evident thatlt is self-evident thatIt is manifest thatIt is well-knownIt is known to all thatIt is widely-accepted thatIt is crystal-cl…

蓝牙客户端QBluetoothSocket的使用——Qt For Android

了解蓝牙 经典蓝牙和低功耗蓝牙差异 经典蓝牙(Bluetooth Classic):分为基本速率/增强数据速率(BR/EDR), 79个信道,在2.4GHz的(ISM)频段。支持点对点设备通信,主要用于实现无线音频流传输,已成…

Ceph:关于Ceph 集群管理的一些笔记

写在前面 准备考试,整理ceph 相关笔记博文内容涉及,Ceph 管理工具 cephadm,ceph 编排器,Ceph CLI 和 Dashboard GUI 介绍理解不足小伙伴帮忙指正 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守…

大数据分析平台释疑专用帖第二弹

不管是想要快速了解BI大数据分析平台,还是想要了解BI和自己的需求匹配度,都可关注我们的释疑专用贴。 1、可以分析直播数据吗? 严格来说,只要能够提供数据,就可以做数据可视化分析,直播数据也同理。 如果…

solr快速上手:整合SolrJ实现客户端操作(九)

0. 引言 我们前面学习了solr的服务端基础操作,实际项目中我们还需要在客户端调用solr,就像调用数据库一样,我们可以基于solrJ来实现对solr的客户端操作 1. SolrJ简介 SolrJ 是 Solr官方提供的 Java 客户端库,主要用于与 Solr 服…

Python 请求分页

文章目录 什么是 Python 中的分页带有下一个按钮的 Python 分页没有下一个按钮的 Python 分页无限滚动的 Python 分页带有加载更多按钮的分页 在本文中,我们将了解分页以及如何克服 Python 中与分页相关的问题。 读完本文后,我们将能够了解 Python 分页以…

经典目标检测YOLO系列(1)YOLO-V1算法及其在VOC2007数据集上的应用

经典目标检测YOLO系列(1)YOLO-V1算法及其在VOC2007数据集上的应用 1 YOLO-V1的简述 1.1 目标检测概述 ​ 目标检测有非常广泛的应用, 例如:在安防监控、手机支付中的人脸检测;在智慧交通,自动驾驶中的车辆检测;在智…

Parallel Desktop中按照的centos在切换root用户时,密码正确,但一直切换不成功,显示su: Authentication failure

目录 一、出现问题二、分析问题三、解决问题四、参考资料 一、出现问题 我的密码明明是输入正确的,但又一直给我报下面的错误 二、分析问题 我怀疑是我密码记错了,所以我点击Log Out,重新去输入了一下密码,发现是正确的我确认…

Build your own unconditional confidence

不要活在既定的社会价值体系中 人类的偏好大多数时候都是愚昧的 I play whatever gods give me 情绪价值稳定 解决问题的能力 Dont label yourself 真正的强者不会吝啬对他人的赞美 敬畏自然,敬畏未知事物 核心是你对这个事情是否感兴趣,觉得有价…

PHP 使用html创建PDF并设置水印

使用TCPDF库给PDF文件加水印,需要注意无法直接使用文本,需要创建水印图片后,通过图片来设置水印效果。 目录 创建PDF 创建合同模板 创建pdf文件 简单创建 设置文档信息 去掉默认页头脚 设置间距 设置字体支持中文 设置图片比例因子 …

代理ip数据采集的优缺点

随着互联网时代的到来,数据已经成为企业发展和决策的关键。但是,不同的网站它对于数据访问的限制和反爬虫措施却是给企业的数据采集带来了挑战。针对这一问题,代理IP数据采集技术应运而生。但是使用代理ip来进行数据采集也有优缺点。 一、代理…

【微信小程序】wxml、wxss、js、json文件介绍

😉博主:初映CY的前说(前端领域) ,📒本文核心:微信小程序的入门介绍 【前言】书接上回,我们知道了一个小程序的构成结构,接下来我们来进一步学习小程序的目录结构中的.wxml、.wxss、.js、.json。 目录 ⭐ 一…

List容器(Java)

文章目录 1.容器介绍1.1 容器接口结构1.2 简单解析 2. List容器创建(Member functions)3. 访问操作(Element access)3.1 get()3.2 Iterator遍历3.3 增强for循环 4. 修改操作(Modifiers)4.1 add()4.2 addAll()4.3 remove()4.4 set() 5. 容量操作(Member functions)5.1 clear() …

傻白入门芯片设计,形式化验证方法学——AveMC工具学习(二十)

目录 一、形式验证方法学 (一)什么是形式化验证? (二)与传统验证的区别? 二、AveMC工具学习 (一)什么是AveMC? (二)AveMC的工作逻辑&#x…

Redis整合jedis 学习

前言 redis简单来讲是内存数据库,因为是将数据存放到内存,因此读写速率高快(传统数据库,不是先从内存转到硬存,慢) 1.jedis连接Redis redis是java操作redis的客户端,通过他我们能通过java语句操控redis。 jedis对于…