先看一个经典的12306案例:

public class SynBlockTest {
public static void main(String[] args) {
// 一份资源
SynWeb12306 web = new SynWeb12306();
// 多份代理
new Thread(web,"黄牛").start();
new Thread(web,"码农").start();
new Thread(web,"黑牛").start();
}
} class SynWeb12306 implements Runnable{
private int ticketNums = 10;// 票数
private boolean flag = true; @Override
public void run() {
while(flag) {
test01();
} } public void test01() {
if(ticketNums <= 0) {
flag = false;
return;
}
// 模拟延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
}

以上代码运行结果:



显然,在没有加锁的情况下,数据时不安全的

下面我么使用代码代码块加锁:
public void test02() {
synchronized(this) {
if(ticketNums <= 0) {
flag = false;
return;
}
// 模拟延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
}

修改后运行测试:

好了数据安全了。

但是,这样锁效率比较低:

在进入synchronized 代码块之前,如果没票了,不用让所有线程都等待。

于是修改代码:

// //double checking
public void test03() {
if(ticketNums <= 0) { // 考虑没有票的情况
flag = false;
return;
}
synchronized(this) {
if(ticketNums <= 0) { // 考虑最后一张票
flag = false;
return;
}
// 模拟延迟
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->" + ticketNums--);
}
}

修改后运行:



好了这就是所谓 的双重检测。

Java 多线程 -- 线程安全 双重检测(double checking)的更多相关文章

  1. Java多线程——线程之间的同步

    Java多线程——线程之间的同步 摘要:本文主要学习多线程之间是如何同步的,如何使用volatile关键字,如何使用synchronized修饰的同步代码块和同步方法解决线程安全问题. 部分内容来自以 ...

  2. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  3. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  4. Java多线程--线程及相关的Java API

    Java多线程--线程及相关的Java API 线程与进程 进程是线程的容器,程序是指令.数据的组织形式,进程是程序的实体. 一个进程中可以容纳若干个线程,线程是轻量级的进程,是程序执行的最小单位.我 ...

  5. Java多线程-线程的同步(同步方法)

    线程的同步是保证多线程安全访问竞争资源的一种手段.线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源.什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些 ...

  6. Java多线程——线程的优先级和生命周期

    Java多线程——线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...

  7. Java多线程——线程的创建方式

    Java多线程——线程的创建方式 摘要:本文主要学习了线程的创建方式,线程的常用属性和方法,以及线程的几个基本状态. 部分内容来自以下博客: https://www.cnblogs.com/dolph ...

  8. Java多线程——线程之间的协作

    Java多线程——线程之间的协作 摘要:本文主要学习多线程之间是如何协作的,以及如何使用wait()方法与notify()/notifyAll()方法. 部分内容来自以下博客: https://www ...

  9. Java多线程——线程的死锁

    Java多线程——线程的死锁 摘要:本文主要介绍了Java多线程中遇到的死锁问题. 部分内容来自以下博客: https://www.cnblogs.com/wy697495/p/9757982.htm ...

随机推荐

  1. VSCode 快速生成 .vue 模版

    VSCode 快速生成 .vue 模版 安装vscode 官网:https://code.visualstudio.com/ 安装 Vetur 插件,识别 vue 文件 插件库中搜索Vetur,点击安 ...

  2. 关于C#中Partial局部类型关键字的使用

    虽然之前在做Winform开发时候,经常遇到Partial关键字,但是最近在代码中看到使用Partial将同名类文件写在多个源文件中,因此想要记录下Partial的详细使用. Partial type ...

  3. sql MySQL5.7 安装 centos docker

    MySQL5.7 安装 1 . 普通安装 # 准备工作 停止以前的数据库并删除配置文件 systemctl stop mysqld rpm -e mysql-community-server-5.7. ...

  4. [noip模拟]难缠的值周生<宽搜>

    难缠的值周生 [问题描述] 小 P 上学总是迟到,迟到了以后常常会被值周生发现.被值周生发现就会给他所在的班级扣分,被扣了分不免要挨班主任的训,这令小 P 很不爽.不过,聪明的他经过观察发现,值周生通 ...

  5. prometheus+grafana实现监控过程的整体流程

    prometheus安装较为简单,下面会省略安装步骤: 一.服务器启动 Prometheus启动 ./prometheus --config.file=prometheus.yml Grafana启动 ...

  6. Scala环境及IDEA配置

    Scala环境及IDEA配置 1 语言介绍 他已经出生15年了,就像明星一样,谁都不可能一开始就人气爆棚粉丝无数,得慢慢混. 成功原因:完全兼容java代码. 身世介绍 Scala在2004年正式问世 ...

  7. 当阿里面试官问我:Java创建线程有几种方式?我就知道问题没那么简单

    这是最新的大厂面试系列,还原真实场景,提炼出知识点分享给大家. 点赞再看,养成习惯~ 微信搜索[武哥聊编程],关注这个 Java 菜鸟. 昨天有个小伙伴去阿里面试实习生岗位,面试官问他了一个老生常谈的 ...

  8. 如何做监控?Google SRE 解密

    监控值班室: @隔壁老王头 SQL执行耗时时间过长,达到了报警阈值[5000ms] 隔壁老王头: @监控值班室 少量报警请忽略,批量关注即可. 监控值班室: @隔壁老王头 订单号[88886666]状 ...

  9. RedHat 6.5 上将系统语言修改为中文

    RedHat 6.5 上将系统语言修改为中文 1.打开终端,输入su -,键入密码,获取超级用户权限. 2.输入cd /etc/sysconfig,进入设置目录. 3.输入vi i18n,进入到配置文 ...

  10. python_Mock基本使用

    ## 1.mock简介 1. py3已将mock集成到unittest库中 2. 为的就是更好的进行单元测试 3. 简单理解,模拟接口返回参数 4. 通俗易懂,直接修改接口返回参数的值 5. 官方文档 ...