7.乐观锁和悲观锁
悲观锁(Pessimistic Lock)顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会 block 直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。

乐观锁(Optimistic Lock)顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。

悲观锁一般使用行锁或表锁,查询时表明该查询是为了修改而查询,当事务未提交前其他连接是不能操作该条数据。

select * from user where id = 1 for update

乐观锁一般使用版本锁,每次修改前查询一次版本,修改时指定查询到的版本。如果版本过期,则修改失败并进入重试逻辑。

update user set name=‘张三’,version = 6 where id =1 and version = 5

8.ThreadLocal
在并发编程的时候,成员变量如果不做任何处理其实是线程不安全的,各个线程都在操作同一个变量,显然是不行的。那么在有一种情况之下,我们需要满足这样一个条件:

变量是同一个,但是每个线程都使用同一个初始值,也就是使用同一个变量的一个新的副本。

这种情况之下 ThreadLocal 就非常使用,比如说 DAO 的数据库连接,我们知道 DAO 是单例的,那么他的属性 Connection 就不是一个线程安全的变量。而我们每个线程都需要使用他,并且各自使用各自的。这种情况,ThreadLocal 就比较好的解决了这个问题。

public final class ConnectionUtil {

private ConnectionUtil() {}private static final ThreadLocal<Connection> conn = new ThreadLocal<>();public static Connection getConn() {Connection con = conn.get();if (con == null) {try {Class.forName("com.mysql.jdbc.Driver");con = DriverManager.getConnection("url", "userName", "password");conn.set(con);} catch (ClassNotFoundException | SQLException e) {// ...}}return con;
}

}

这样子,都是用同一个连接,但是每个连接都是新的,是同一个连接的副本。

那么实现机制是如何的呢?

1、每个 Thread 对象内部都维护了一个 ThreadLocalMap 这样一个 ThreadLocal 的 Map,可以存放若干个 ThreadLocal。

2、当我们在调用 get()方法的时候,先获取当前线程,然后获取到当前线程的 ThreadLocalMap 对象,如果非空,那么取出 ThreadLocal 的 value,否则进行初始化,初始化就是将 initialValue 的值 set 到 ThreadLocal 中。

public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}

3、当我们调用 set() 方法的时候,很常规,就是将值设置进 ThreadLocal 中。

4、总结:当我们调用 get 方法的时候,其实每个当前线程中都有一个 ThreadLocal。每次获取或者设置都是对该 ThreadLocal 进行的操作,是与其他线程分开的。

5、应用场景:当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值的时候最适合使用 ThreadLocal。

6、其实说再多也不如看一下源码来得清晰。如果要看源码,其中涉及到一个 WeakReference 和一个 Map,这两个地方需要了解下,这两个东西分别是 Java 的弱引用,也就是 GC 的时候会销毁该引用所包裹(引用)的对象,这个 threadLocal 作为 key 可能被销毁,但是只要我们定义成他的类不卸载,这个强引用就始终引用着这个 ThreadLocal 的,永远不会被 gc 掉,和 HashMap 差不多。

事实上,从本质来讲,就是每个线程都维护了一个 map,而这个 map 的 key 就是 ThreadLocal,而值就是我们 set 的那个值,每次线程在 get 的时候,都从自己的变量中取值,既然从自己的变量中取值,那肯定就不存在线程安全问题,总体来讲,ThreadLocal 这个变量的状态根本没有发生变化,他仅仅是充当一个 key 的角色,另外提供给每一个线程一个初始值。如果允许的话,我们自己就能实现一个这样的功能,只不过恰好 JDK 就已经帮我们

java 乐观锁和悲观锁,Threadlocal相关推荐

  1. **Java有哪些悲观锁的实现_面试4连问:乐观锁与悲观锁的概念、实现方式、场景、优缺点?...

    推荐阅读: 数据库面试4连问:分库分表,中间件,优缺点,如何拆分? 终极手撕之架构大全:分布式+框架+微服务+性能优化,够不够? 消息队列面试,你能顶得住面试官这波10大连环炮的攻势吗? 01 乐观锁 ...

  2. 详解各种锁:CAS、共享锁、排它锁、互斥锁、悲观锁、乐观锁、行级锁、表级锁、页级锁、死锁、JAVA对CAS的支持、ABA问题、AQS原理

    共享锁(S锁) 又称为读锁,可以查看但无法修改和删除的一种数据锁.如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排它锁.获准共享锁的事务只能读数据,不能修改数据. 共享锁下其它用 ...

  3. Java并发篇_乐观锁与悲观锁

    乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展. 一.引入概念 1.悲观锁 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次 ...

  4. Java多线程学习总结(5)——乐观锁和悲观锁的基本概念、实现方式(含实例)、适用场景及常见面试题

     分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!点击浏览教程 一.基本概念 乐观锁和悲观锁是两种思想,用于解决并发场景下的数据竞争问题. 乐观锁 ...

  5. Java并发 乐观锁和悲观锁 乐观锁的一种实现方式CAS

    为什么80%的码农都做不了架构师?>>>    首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人 ...

  6. Java之乐观锁和悲观锁

    Java之乐观锁和悲观锁 乐观锁 用到的机制是CAS(Compare and Swap),每个线程都可以访问,只有在提交数据的时候,检查是否违反了数据的完整性.如果发生冲突失败重试,直到成功为止.乐观 ...

  7. Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    Java并发问题–乐观锁与悲观锁以及乐观锁的一种实现方式-CAS </h1><div class="clear"></div><div c ...

  8. java中的锁(悲观锁、乐观锁、可重入锁、不可重入锁、公平锁、非公平锁、自旋锁、阻塞锁...)

    Lock接口 1.简介.地位.作用 ① 锁是一种工具,用于控制对共享资源的访问 ② Lock和synchronized,这两个是最常见的锁,它们都可以达到线程安全的目的,但是在使用和功能上又有较大的不 ...

  9. java中的锁---乐观锁与悲观锁的区别

    锁,是开发中不得不掌握的一个知识点. 在面试中也会经常问到.其中乐观锁与悲观锁为最常见.首先介绍下两种锁 一:乐观锁: 1 介绍: 它的心态很好,每次别人使用它的时候,它会乐观的认为别人不修改数据,所 ...

最新文章

  1. 精选SpringBoot+Vue开发的开源系统(前端+后端+小程序)
  2. 多级反馈队列调度算法原理
  3. 阿里JAVA面试题剖析:一般实现分布式锁都有哪些方式?使用 Redis 如何设计分布式锁?...
  4. 数据结构:希尔排序(shell sort)
  5. 美团悄悄进入企业早餐,其战略目的为高频带低频?
  6. linux使用qemu教程,Linux:使用 QEMU 测试 U-BOOT的步骤
  7. 3750交换机简要配置手册(中文)
  8. jquery交换数组元素位置_跟我一起学jQuery——第一集
  9. 话里话外:流程管理评价的两大要素
  10. 【转】常见面试之机器学习算法思想简单梳理
  11. FreeRTOS软件定时器
  12. leetcode幂集
  13. 【UVA】P1510 Neon Sign
  14. 第三章 枚举(炸弹人、火柴棍等式、全排列)
  15. C++中vector容器和普通数组的区别
  16. Vue开发实例(15)之动态路由
  17. TDS210示波器的应用
  18. Every-SG游戏
  19. 分享简单的记账方法,轻松搜索账目查看
  20. 基于单片机的压力流量报警器(附代码+仿真+论文)

热门文章

  1. rabbitmq 学习 之 心跳检测(13)
  2. Oracle Wrap破解
  3. Hive on Tez配置过程
  4. mysql导出数据库所有表和数据
  5. poiexcel 读取引用列_java用poi读取Excel表格中的数据
  6. 支付宝不用了,如何注销
  7. Oracle存储过程实现人民币大小写转换
  8. 如何解决Windows10系统开机提示,没有默认的邮件客户端
  9. 这些韩语书你看过么-推荐你们看呀呀
  10. Word 2003 视频教程-Word 字体设置(转)