首先还原一个线程不安全的事故现场:

运行结果:

明显是有问题的,相同的票售出了多次。

基于Oracle实现简单的分布式锁

创建一个仅有一个主键字段的表:

数据库实体类:

@Table(name = "oracle_lock")
@Setter
@Getter
@AllArgsConstructor
public class OracleLockEntity {@Id@Column(name = "id")private String id;
}

Mapper接口:

/*** @author Dongguabai* @date 2018-07-20 11:01*/
public interface OracleLockMapper extends Mapper<OracleLockEntity> {
}

Lock接口的方法太多,现在建一个中间实现类:

/*** @author Dongguabai* @date 2018-07-20 11:13*/
public class LockDecorator implements Lock{@Overridepublic void lock() {}@Overridepublic void lockInterruptibly() throws InterruptedException {}@Overridepublic boolean tryLock() {return false;}@Overridepublic boolean tryLock(long time, TimeUnit unit) throws InterruptedException {return false;}@Overridepublic void unlock() {}@Overridepublic Condition newCondition() {return null;}
}

编写数据库锁:

/*** Oracle分布式锁* 注意:1.性能较差* 2.可能会出现死锁(比如解锁的时候数据库挂了)* 3.代码复杂* 4.不可重入** @author Dongguabai* @date 2018-07-20 10:56*/
@Component("simpleOracleLock")
@Slf4j
public class SimpleOracleLock extends LockDecorator {public static final String LOCK_ID = "1";public static final OracleLockEntity LOCK_ORACLE_ENTITY = new OracleLockEntity(LOCK_ID);@Autowiredprivate OracleLockMapper oracleLockMapper;/*** 非阻塞式加锁** @return*/@Overridepublic boolean tryLock() {try {oracleLockMapper.insert(LOCK_ORACLE_ENTITY);} catch (Exception e) {log.info("尝试加锁失败!");return false;}return true;}/*** 解锁*/@Overridepublic void unlock() {oracleLockMapper.deleteByPrimaryKey(LOCK_ID);}/*** 阻塞式加锁*/@Overridepublic void lock() {if (!tryLock()) {int randomSleepMillis = new Random().nextInt(100);try {Thread.sleep(randomSleepMillis);} catch (InterruptedException e) {log.info("尝试加锁失败,线程sleep{}毫秒!", randomSleepMillis);}lock();}}}

运行测试:

    @Resource(name = "simpleOracleLock")private Lock simpleOracleLock;@Testpublic void test22() throws InterruptedException {RunnableImpl runnable = new RunnableImpl();Thread t1 = new Thread(runnable, "售票窗口一");Thread t2 = new Thread(runnable, "售票窗口二");Thread t3 = new Thread(runnable, "售票窗口三");Thread t4 = new Thread(runnable, "售票窗口四");t1.start();t2.start();t3.start();t4.start();//主线程等待子线程执行完毕Thread.currentThread().join();}class RunnableImpl implements Runnable {@Overridepublic void run() {while (sum > 0) {simpleOracleLock.lock();try {System.out.println(Thread.currentThread().getName() + "现在卖了第" + (sum--) + "张票");}catch (Exception e){}finally {simpleOracleLock.unlock();}try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}}}

运行结果:

符合要求,按照顺序票一个个卖出去了。

简单基于Oracle实现分布式锁相关推荐

  1. etcd 笔记(08)— 基于 etcd 实现分布式锁

    1. 为什么需要分布式锁? 在分布式环境下,数据一致性问题一直是个难点.分布式与单机环境最大的不同在于它不是多线程而是多进程.由于多线程可以共享堆内存,因此可以简单地采取内存作为标记存储位置.而多进程 ...

  2. nx set 怎么实现的原子性_基于Redis的分布式锁实现

    前言 本篇文章主要介绍基于Redis的分布式锁实现到底是怎么一回事,其中参考了许多大佬写的文章,算是对分布式锁做一个总结 分布式锁概览 在多线程的环境下,为了保证一个代码块在同一时间只能由一个线程访问 ...

  3. 基于Redis的分布式锁和Redlock算法

    来自:后端技术指南针 1 前言 今天开始来和大家一起学习一下Redis实际应用篇,会写几个Redis的常见应用. 在我看来Redis最为典型的应用就是作为分布式缓存系统,其他的一些应用本质上并不是杀手 ...

  4. 基于 Redis 的分布式锁到底安全吗?

    [完整版] 网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现 ...

  5. js 拉勾网效果_Node.js 中实践基于 Redis 的分布式锁实现

    在一些分布式环境下.多线程并发编程中,如果对同一资源进行读写操作,避免不了的一个就是资源竞争问题,通过引入分布式锁这一概念,可以解决数据一致性问题. 作者简介:五月君,Nodejs Developer ...

  6. php使用redis分布式锁,php基于redis的分布式锁实例详解

    在使用分布式锁进行互斥资源访问时候,我们很多方案是采用redis的实现. 固然,redis的单节点锁在极端情况也是有问题的,假设你的业务允许偶尔的失效,使用单节点的redis锁方案就足够了,简单而且效 ...

  7. java如何保证redis设置过期时间的原子性_redis专题系列22 -- 如何优雅的基于redis实现分布式锁

    几个概念 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一JVM中有效果,因为线程锁的实现在根本上是依靠线程之间共享内存实现的,比 ...

  8. 基于 Zookeeper 的分布式锁实现

    1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个"类 Unix ...

  9. 基于Redis的分布式锁到底安全吗(上)?

    网上有关Redis分布式锁的文章可谓多如牛毛了,不信的话你可以拿关键词"Redis 分布式锁"随便到哪个搜索引擎上去搜索一下就知道了.这些文章的思路大体相近,给出的实现算法也看似合 ...

最新文章

  1. java加载一个来自项目之外的java文件,执行其main方法的一种实现方式
  2. [系统安全] 八.Windows漏洞利用之CVE-2019-0708复现及防御详解
  3. 监听列表ListVIew的滑动状态
  4. akcms在模板文件中书写{php},AKCMS支持灵活的模板插件
  5. excel去重怎么操作_excel数据技巧:不用公式如何快速去重
  6. java学习(76):GUL单选按钮和复选按钮
  7. 从任意网页上摘取酷炫Jquery效果为自己使用的方法
  8. ios 通过kvc修改属性会触发kvo_iOS开发-KVC和KVO的理解
  9. php 的超全局数组,PHP超全局数组(Superglobals)介绍
  10. Java8 本地DateTime API
  11. WinCE下直接启动自己应用程序的方法
  12. 【注意力机制】一系列关于attention的高效改进大集合
  13. 3.SOA架构:服务和微服务分析及设计--- 理解服务与微服务的层次
  14. BP神经网络做数据预测
  15. java 设置压缩文件大小不变_为什么把文件压缩后,文件大小却不变呢?
  16. windows保护无法启动修复服务器,Win10系统提示Windows资源保护无法启动修复服务怎么办...
  17. 记dubbo consumer服务因订阅其他有异常的服务导致超时的问题
  18. mysql中data后面加什么_mysql中data_format用法
  19. VS2017调用Matlab2016b进行绘图
  20. 【Turtle绘图系列】超火皮卡丘大全,可爱到爆炸~

热门文章

  1. 静态资源cdn服务是什么
  2. 千年虫及UNIX时间
  3. swagger2配置权限认证参数Authorize
  4. c 语言往字符数组里面赋值,关于c 语言字符数组的赋值
  5. Centos5.3下构建数据完整性监测系统Tripwire(2.使用技巧和安全处理)
  6. vue脚手架基础API全面讲解【内附多个案例】
  7. tanh Function
  8. (二)python网络爬虫(理论+实战)——爬虫分类和基本流程
  9. 内固定取出术后护理_内固定物取出方法及手术技巧图文汇总
  10. 方舟找不到mod服务器了,方舟生存进化灭绝MOD全图文攻略 方舟灭绝MOD上手指南_MOD介绍及服务器设置_游侠网...