Java与MySQL中的锁以及保证线程安全的方式

1 概述

无论是存在硬盘里的数据还是存在内存中的数据,只要不是像Redis那样只支持单线程访问,就都存在线程安全问题。通常,在代码中,面对线程安全问题的态度,分为【悲观】和【乐观】。本文从这两个角度对Java与MySQL中的锁及保证线程安全的方式进行一个对比,尽量提炼出其中的相似之处。文中的某些地方会把Java中的【线程】与MySQL中的【事务】统称为【线程】。

2 悲观

【悲观】认为,在当前环境下,极有可能发生线程安全问题,因此,需要把多线程共享的数据上一个重锁,在某个线程拥有这个数据的锁期间,其他线程无法对这个数据进行访问与操作。

2.1 Java的悲观锁

Java里面著名的synchronizedReentrantLock就是悲观锁。一旦某个线程抢到了这个资源,其他线程就得等待了。可以保证线程安全,但是会拖慢系统速度——速度和安全向来是一对矛盾的概念。

例如,HashMap这个集合,线程A、B同时进行put()操作,他俩的节点映射在了同一数组下标。A执行到最后一步刚要把节点加在链表后面时,被挂起了。这时B把自己的节点加在了链表后面。然后A继续操作,就把B节点覆盖掉了。

为了解决这个问题,Java加入了HashTable。它和HashMap唯一的区别就是在get和put等关键方法上面加了synchronized修饰。从此两个put线程再也进不去同一个HashTable,保障了线程安全。

2.2 MySQL里的悲观锁

MySQL的事务隔离级别中,最高级别的串行化可以保证线程安全。例如这个简易的收益表:
在这里插入图片描述
在事务A加数剧的时候,事务B别说对表进行写操作了,他连读都读不了。此时线程很安全。

2.3 减小悲观锁的粒度

2.3.1 Java代表:ConcurrentHashMap

ConcurrentHashMap保证线程安全的方式相当复杂,这里举例一种较简单的情况:ConcurrentHashMap已经被成功new出来,线程A和线程B分别要put一个结点,它们分别被映射到了数组下表为1和3的地方。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值