先看一个经典的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--);
}
}

修改后运行:



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

最新文章

  1. 变通实现微服务的per request以提高IO效率(三)
  2. C++ Daily 《1》----关于对象
  3. MongoDB 的 GridFS 详细分析
  4. BZOJ4155 : [Ipsc2015]Humble Captains
  5. javascript笔记2-引用类型
  6. AD采样问题总结
  7. programming ruby
  8. Java处理文件小例子--获取全国所有城市的坐标
  9. MySql拾遗
  10. C#重写Equals方法步骤
  11. 开发网站相关知识html和javascript
  12. 如何解决RK3168或者RK系列MASKROM的问题
  13. [Swift]LeetCode653. 两数之和 IV - 输入 BST | Two Sum IV - Input is a BST
  14. 启航 - cache2go源码分析
  15. word2vec概述
  16. 需要重写URL但请求的目录不存在报404
  17. Linux whereis命令详解
  18. Sql Server插入数据并返回自增ID,@@IDENTITY,SCOPE_IDENTITY和IDENT_CURRENT的区别(转载)
  19. Java之旅_高级教程_实例_打印图形
  20. CSS多div放一行

热门文章

  1. Python终端打印彩色文字
  2. ajax请求以及递归
  3. #VScodd集成Git Bash 命令行 #怎么把Git Bash集成到VScode
  4. Three中的动画实现-[three.js]
  5. web自动化浏览器chrome和驱动chromedriver
  6. 多转一ETH(ERC20代币汇集)
  7. 微信小程序引入腾讯地图API方法
  8. stdio.h file not found mac catalina clion 头文件 找不到
  9. javascript中的constructor
  10. Linux基础篇,Shell