先看一个经典的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. CodeForces - 1244E

    题意:给n个数,可以有k次的 + 1或 - 1,在k次操作之内,让n个数的最大值和最小值差最小. 思路:要让max和min的差值最小,也就等同于min--,max++,如果k==0结束操作,或者min ...

  2. socket,实现服务器和客户端对话

    服务器: #define _CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string>#include<WinSock ...

  3. Python第十章-模块和包

    模块和包 我们以前的代码都是写在一个文件中, 而且代码也比较短. 假设我们现在要写一个大的系统, 不可能把代码只写到一个文件中, 迫切想把代码写到不同的文件中, 并且能够在一个文件使用另一个文件中代码 ...

  4. iOS 第三方库

    网络 AFNetworking HTTP网络库 Reachability 网络监测 UI.布局 Masonry AutoLayout SnapKit AutoLayout Swift TOWebVie ...

  5. sql select sql查询

    select 一.课上练习代码 1 查询所有学生信息 select * from tb_student; select * from tb_teacher; 2 查询所有课程名称及学分(投影和别名) ...

  6. [bzoj1029]建筑抢修<贪心>

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1029 解析:这也算bzoj中比较简单的一道题,其实想通了就是非常的简单. 这题用贪心的方式 ...

  7. 详谈XSS防御方法

      1.HttpOnly 严格的说,httponly并非为了对抗XSS,它解决的是XSS后的Cookie劫持攻击.Cookie设置了httponly之后,JavaScript读不到该cookie的值. ...

  8. Codeforces Round #627 (Div. 3)

    1324A - Yet Another Tetris Problem(思维) 题意 给一个数组,每一个数组中的元素大小表示在竖直方向的方块数量,元素相邻怎竖直方向的方块也相邻,类似于俄罗斯方块当底层被 ...

  9. I、恋爱之子

    链接:https://ac.nowcoder.com/acm/contest/3570/I 来源:牛客网 题目描述 最近ZSC和他的女朋友NULL吵架了.因为ZSC是一个直男,他不知道该怎么办,于是他 ...

  10. #VScodd集成Git Bash 命令行 #怎么把Git Bash集成到VScode

    配置 Step1. File-Preferences-Setting Step2. 搜索"terminal>integrated>shell A" Step3. 找到t ...