• Java中的synchronized、volatile、ThreadLocal


    synchronized内置锁

    用处

    1. 加到方法上面

    2. 以同步块的形式使用

      最大的作用是确保多个线程在同一时刻,只能有一个线程处于方法和同步块之中.

      这样保证了线程对变量访问的可见性排他性

      synchronized关键字,是由java语言本身为我们提供的,所以说我们习惯性把synchronized关键字称为内置锁.

      synchronized锁的其实是一个具体的对象

      每个对象在内存中会被编译成class文件,内存的对象头上有一个标志位, 标志位上有1~2个字节的锁

      使用synchronized关键字,就是线程去抢那个标志位,谁把标志位指向了自己,谁就抢到了锁,这又产生了对象锁,类锁的概念.

    对象锁

    • 方法直接用synchronuzed关键字修饰的时候

    • 在方法体里面:

      synchronized(this) {
        
      }
      

      的时候.

    • 两个线程同时锁相同的对象,先获得锁那个线程先运行完毕另一个线程才开始运行

    • 两个线程锁不同的对象,意味着两个线程是可以同时进行的.

    类锁

    • 方法定义成static,并使用了synchronized关键字

    对象锁和类锁之间

    • 锁的东西是不一样的
    • 锁不同的对象,锁也是不同的
    • 类对象无论怎么做,虚拟机保证了每个类的class对象有且只有一个

    注:

    • 用Spring框架的时候,Spring框架没有做特殊设置的话,Spring为我们new出的对象实例有且只有一个,这时候用synchronized可以保证锁定是唯一的一个对象.
    • 如果配置了Spring允许new出多个对象,这时候再来加锁的时候千万要注意synchronized关键字锁的会不会是同一个对象.

    volatile关键字,最轻量的同步机制

    • volatile关键字是由虚拟机为我们提供的一个最轻量级的同步机制

    • 某个变量加上volatile关键字后,其实是告诉虚拟机每次要用变量的时候从主内存中读取,

    • volatile在使用的时候,不会对读取写入加锁,所以是最轻量的同步机制,效率也是最高的

    • volatile不是线程安全的,只能保证某个变量的可见性,不能保证变量的原子性

      比如:

      如果是:

      public void setAge(){
        age = age + 20;
      }
      

      的话,虚拟机并不能保证操作是原子性的.

      • 只有一个线程写,多个线程读是volatile最常使用的场景

        jdk源码里,使用volatile关键字的地方相当多

    ThreadLocal的使用

    线程变量

    • 可以确保每个线程他只使用自己那部分的

      在线程里定义一个变量,只要以ThreadLocal包装,可以确保每个线程只会使用自己的一份拷贝

    • 链接池里面会使用ThreadLocal,每一个线程拥有自己独有的链接.

    • Spring事务处理也有用到ThreadLocal

  • 相关阅读:
    excel+requests管理测试用例接口自动化框架
    MyBatis 的在使用上的注意事项及其辨析
    前端内容记录之常用置标
    react学习(三——实战项目)
    MySQL 数据处理之增删改
    【数据结构与算法】第四篇:AVL树
    Git配置
    springcloud-Eureka
    MYSQL 按照身份证筛选年龄和性别
    JDBC知识【JDBC API详解】第三章下篇
  • 原文地址:https://blog.csdn.net/gaofenglxx/article/details/119279709