HW14基于规则化的终身学习Regularization-based Lifelong Learning

news2025/2/25 14:23:49

文章目录

  • 一、介绍-终身学习
      • 目标
      • 数据集
      • 任务
      • 示例代码-准备数据
      • 模型体系结构
      • 样本代码-训练和评估
      • Training Pipeline:
      • MAS - Memory Aware Synapse
      • SI
      • SCP - Sliced Cramer Preservation
  • 二、实验
    • 1、baseline
    • 2、EWC
    • 3、MAS
    • 4、SI
    • 5、RWalk
    • 6、SCP


一、介绍-终身学习

目标

一个模型可以打败所有的任务!
在这里插入图片描述
条件:模型按顺序学习不同的任务!(在训练时间内)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数据集

旋转的MNIST(由TAs生成)
在这里插入图片描述

任务

●一共五个任务,每个任务有10个训练周期用于训练。
●每种方法的训练模型都要花费~20分钟。(Tesla T4)
●每种方法的训练模型都要花费~60分钟。(Tesla K80)

示例代码-指南:●实用工具●准备数据●准备模型●训练和评估●方法●图函数

示例代码-准备数据

●准备数据:○旋转和转换○Dataloaders and Arguments○可视化
在这里插入图片描述

模型体系结构

在这里插入图片描述

样本代码-训练和评估

●训练:○顺序训练。○添加正则化项并更新它。
●评估:○使用特殊metric。

Training Pipeline:

在这里插入图片描述
在这里插入图片描述

MAS - Memory Aware Synapse

通过从模型的最后一层获取输出来实现全局版本。
在这里插入图片描述

SI

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SCP - Sliced Cramer Preservation

在这里插入图片描述
提出基于分布式的距离,以防止快速不妥协,避免高估参数的重要性。
在这里插入图片描述

二、实验

1、baseline

没有加入正则化项

# Baseline
class baseline(object):
  """
  baseline technique: do nothing in regularization term [initialize and all weight is zero]
  """
  def __init__(self, model, dataloader, device):
    self.model = model
    self.dataloader = dataloader
    self.device = device
    # extract all parameters in models
    self.params = {n: p for n, p in self.model.named_parameters() if p.requires_grad} 
    
    # store current parameters
    self.p_old = {} 

    # generate weight matrix
    self._precision_matrices = self._calculate_importance()  

    for n, p in self.params.items():
      # keep the old parameter in self.p_old
      self.p_old[n] = p.clone().detach() 

  def _calculate_importance(self):
    precision_matrices = {} 
    # initialize weight matrix(fill zero)
    for n, p in self.params.items(): 
      precision_matrices[n] = p.clone().detach().fill_(0)

    return precision_matrices

  def penalty(self, model: nn.Module):
    loss = 0
    for n, p in model.named_parameters():
      _loss = self._precision_matrices[n] * (p - self.p_old[n]) ** 2
      loss += _loss.sum()
    return loss
  
  def update(self, model):
    # do nothing
    return
# Baseline
print("RUN BASELINE")
model = Model()
model = model.to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)

# initialize lifelong learning object (baseline class) without adding any regularization term.
lll_object=baseline(model=model, dataloader=None, device=device)
lll_lambda=0.0
baseline_acc=[]
task_bar = tqdm.auto.trange(len(train_dataloaders),desc="Task   1")

# iterate training on each task continually.
for train_indexes in task_bar:
  # Train each task
  model, _, acc_list = train(model, optimizer, train_dataloaders[train_indexes], args.epochs_per_task, 
                  lll_object, lll_lambda, evaluate=evaluate,device=device, test_dataloaders=test_dataloaders[:train_indexes+1])
  
  # get model weight to baseline class and do nothing!
  lll_object=baseline(model=model, dataloader=train_dataloaders[train_indexes],device=device)
  
  # new a optimizer
  optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)
  
  # Collect average accuracy in each epoch
  baseline_acc.extend(acc_list)
  
  # display the information of the next task.
  task_bar.set_description_str(f"Task  {train_indexes+2:2}")

# average accuracy in each task per epoch! 
print(baseline_acc)
print("==================================================================================================")

[92.58999999999999, 94.64, 95.77, 96.13000000000001, 97.14, 97.41, 97.47, 97.64, 97.45, 98.00999999999999, 95.545, 95.76, 95.52000000000001, 95.64999999999999, 95.43, 95.61999999999999, 95.145, 95.355, 95.135, 95.52000000000001, 91.06666666666668, 89.78, 89.38333333333333, 89.49000000000001, 87.72666666666667, 88.55333333333334, 88.09333333333332, 87.38666666666667, 87.83333333333333, 86.75, 82.02000000000001, 79.6725, 79.28, 79.135, 79.34750000000001, 78.0925, 78.6275, 78.995, 78.17, 78.01249999999999, 74.888, 73.388, 71.65, 72.104, 71.682, 70.146, 70.874, 70.81200000000001, 69.728, 70.256]
在这里插入图片描述

2、EWC

ewc类应用EWC算法来计算正则项。我们想让我们的模型连续学习10个任务。这里我们展示了一个简单的例子,让模型连续学习两个任务(任务A和任务B)。在EWC算法中,损失函数的定义如下所示:
在这里插入图片描述
假设我们有一个具有两个以上参数的神经网络。Fi对应于第i护卫。F的定义如下所示:
在这里插入图片描述
我们只取矩阵的对角线值来近似每个参数的Fi。

# EWC
class ewc(object):
  """
  @article{kirkpatrick2017overcoming,
      title={Overcoming catastrophic forgetting in neural networks},
      author={Kirkpatrick, James and Pascanu, Razvan and Rabinowitz, Neil and Veness, Joel and Desjardins, Guillaume and Rusu, Andrei A and Milan, Kieran and Quan, John and Ramalho, Tiago and Grabska-Barwinska, Agnieszka and others},
      journal={Proceedings of the national academy of sciences},
      year={2017},
      url={https://arxiv.org/abs/1612.00796}
  }
  """
  def __init__(self, model, dataloader, device, prev_guards=[None]):
    self.model = model
    self.dataloader = dataloader
    self.device = device
    # extract all parameters in models
    self.params = {n: p for n, p in self.model.named_parameters() if p.requires_grad} 
    
    # initialize parameters
    self.p_old = {}
    # save previous guards
    self.previous_guards_list = prev_guards

    # generate Fisher (F) matrix for EWC
    self._precision_matrices = self._calculate_importance()                   

    # keep the old parameter in self.p_old
    for n, p in self.params.items():
      self.p_old[n] = p.clone().detach()       

  def _calculate_importance(self):
    precision_matrices = {}
    # initialize Fisher (F) matrix(all fill zero)and add previous guards
    for n, p in self.params.items(): 
      precision_matrices[n] = p.clone().detach().fill_(0)                 
      for i in range(len(self.previous_guards_list)):
        if self.previous_guards_list[i]:
          precision_matrices[n] += self.previous_guards_list[i][n]

    self.model.eval()
    if self.dataloader is not None:
      number_data = len(self.dataloader)
      for data in self.dataloader:
        self.model.zero_grad()
        # get image data
        input = data[0].to(self.device)
          
        # image data forward model
        output = self.model(input)
          
        # Simply use groud truth label of dataset.  
        label = data[1].to(self.device)
          
        # generate Fisher(F) matrix for EWC     
        loss = F.nll_loss(F.log_softmax(output, dim=1), label)
        loss.backward()   

        for n, p in self.model.named_parameters():
          # 获取每个参数的梯度并求平方,然后在所有验证集中求平均值。     
          precision_matrices[n].data += p.grad.data ** 2 / number_data   
                                                                
      precision_matrices = {n: p for n, p in precision_matrices.items()}
    return precision_matrices

  def penalty(self, model: nn.Module):
    loss = 0
    for n, p in model.named_parameters():
      # generate the final regularization term by the ewc weight (self._precision_matrices[n]) and the square of weight difference ((p - self.p_old[n]) ** 2).  
      _loss = self._precision_matrices[n] * (p - self.p_old[n]) ** 2
      loss += _loss.sum()
    return loss
  
  def update(self, model):
    # do nothing
    return 

lll_lambda=100

[92.49000000000001, 94.62, 95.6, 96.17, 96.67, 97.21, 97.26, 97.48, 97.72, 97.78, 95.57, 96.035, 95.72, 95.88499999999999, 95.725, 95.795, 95.22, 95.275, 95.565, 95.46, 91.23666666666666, 89.55666666666667, 89.07333333333334, 88.04666666666667, 88.28999999999999, 87.44666666666667, 87.19999999999999, 87.97666666666667, 87.0, 87.14, 82.29250000000002, 80.735, 80.35749999999999, 80.8175, 80.7775, 79.1975, 80.59750000000001, 79.66250000000001, 79.62, 80.5825, 74.80399999999999, 74.07600000000001, 73.082, 72.012, 70.48400000000001, 71.848, 72.344, 72.29599999999999, 71.736, 71.37]

在这里插入图片描述

3、MAS

在这里插入图片描述

class mas(object):
  """
  @article{aljundi2017memory,
      title={Memory Aware Synapses: Learning what (not) to forget},
      author={Aljundi, Rahaf and Babiloni, Francesca and Elhoseiny, Mohamed and Rohrbach, Marcus and Tuytelaars, Tinne},
      booktitle={ECCV},
      year={2018},
      url={https://eccv2018.org/openaccess/content_ECCV_2018/papers/Rahaf_Aljundi_Memory_Aware_Synapses_ECCV_2018_paper.pdf}
  }
  """
  def __init__(self, model: nn.Module, dataloader, device, prev_guards=[None]):
    self.model = model 
    self.dataloader = dataloader
    # extract all parameters in models
    self.params = {n: p for n, p in self.model.named_parameters() if p.requires_grad} 
    
    # initialize parameters
    self.p_old = {} 
    
    self.device = device

    # save previous guards
    self.previous_guards_list = prev_guards
    
    # generate Omega(Ω) matrix for MAS
    self._precision_matrices = self.calculate_importance() 

    # keep the old parameter in self.p_old
    for n, p in self.params.items():
      self.p_old[n] = p.clone().detach() 
  
  def calculate_importance(self):
    precision_matrices = {}
    # initialize Omega(Ω) matrix(all filled zero)
    for n, p in self.params.items():
      precision_matrices[n] = p.clone().detach().fill_(0) 
      for i in range(len(self.previous_guards_list)):
        if self.previous_guards_list[i]:
          precision_matrices[n] += self.previous_guards_list[i][n]

    self.model.eval()
    if self.dataloader is not None:
      num_data = len(self.dataloader)
      for data in self.dataloader:
        self.model.zero_grad()
        output = self.model(data[0].to(self.device))
        ################################################################
        #####  TODO: generate Omega(Ω) matrix for MAS.  #####       
        l2_norm = output.norm(2, dim=1).pow(2).mean()
        l2_norm.backward()   

        for n, p in self.model.named_parameters():
          # get the gradient of each parameter and square it, then average it in all validation set.                          
          precision_matrices[n].data += p.grad.data ** 2 / num_data   
        ################################################################                  
    
      precision_matrices = {n: p for n, p in precision_matrices.items()}
    return precision_matrices

  def penalty(self, model: nn.Module):
    loss = 0
    for n, p in model.named_parameters():
      _loss = self._precision_matrices[n] * (p - self.p_old[n]) ** 2
      loss += _loss.sum()
    return loss

  def update(self, model):
    # do nothing
    return 

lll_lambda=0.2
在这里插入图片描述

4、SI

# SI
class si(object):
  """
  @article{kirkpatrick2017overcoming,
      title={Overcoming catastrophic forgetting in neural networks},
      author={Kirkpatrick, James and Pascanu, Razvan and Rabinowitz, Neil and Veness, Joel and Desjardins, Guillaume and Rusu, Andrei A and Milan, Kieran and Quan, John and Ramalho, Tiago and Grabska-Barwinska, Agnieszka and others},
      journal={Proceedings of the national academy of sciences},
      year={2017},
      url={https://arxiv.org/abs/1612.00796}
  }
  """
  def __init__(self, model, dataloader, epsilon, device):
    self.model = model
    self.dataloader = dataloader
    self.device = device
    self.epsilon = epsilon
    # extract all parameters in models
    self.params = {n: p for n, p in self.model.named_parameters() if p.requires_grad}
    
    self._n_p_prev, self._n_omega = self._calculate_importance() 
    self.W, self.p_old = self._init_()
    

  def _init_(self):
    W = {}
    p_old = {}
    for n, p in self.model.named_parameters():
      n = n.replace('.', '__')
      if p.requires_grad:
        W[n] = p.data.clone().zero_()
        p_old[n] = p.data.clone()
    return W, p_old

  def _calculate_importance(self):
    n_p_prev = {}
    n_omega = {}

    if self.dataloader != None:
      for n, p in self.model.named_parameters():
        n = n.replace('.', '__')
        if p.requires_grad:
          # Find/calculate new values for quadratic penalty on parameters
          p_prev = getattr(self.model, '{}_SI_prev_task'.format(n))
          W = getattr(self.model, '{}_W'.format(n))
          p_current = p.detach().clone()
          p_change = p_current - p_prev
          omega_add = W/(p_change**2 + self.epsilon)
          try:
            omega = getattr(self.model, '{}_SI_omega'.format(n))
          except AttributeError:
            omega = p.detach().clone().zero_()
          omega_new = omega + omega_add
          n_omega[n] = omega_new
          n_p_prev[n] = p_current

          # Store these new values in the model
          self.model.register_buffer('{}_SI_prev_task'.format(n), p_current)
          self.model.register_buffer('{}_SI_omega'.format(n), omega_new)

    else:
      for n, p in self.model.named_parameters():
        n = n.replace('.', '__')
        if p.requires_grad:
          n_p_prev[n] = p.detach().clone()
          n_omega[n] = p.detach().clone().zero_()
          self.model.register_buffer('{}_SI_prev_task'.format(n), p.detach().clone())
    return n_p_prev, n_omega

  def penalty(self, model: nn.Module):
    loss = 0.0
    for n, p in model.named_parameters():
      n = n.replace('.', '__')
      if p.requires_grad:
        prev_values = self._n_p_prev[n]
        omega = self._n_omega[n]
        _loss = omega * (p - prev_values) ** 2
        loss += _loss.sum()
    return loss
  
  def update(self, model):
    for n, p in model.named_parameters():
      n = n.replace('.', '__')
      if p.requires_grad:
        if p.grad is not None:
          self.W[n].add_(-p.grad * (p.detach() - self.p_old[n]))
          self.model.register_buffer('{}_W'.format(n), self.W[n])
        self.p_old[n] = p.detach().clone()
    return 

lll_lambda=50
在这里插入图片描述

5、RWalk

在这里插入图片描述

6、SCP

在这里插入图片描述

def sample_spherical(npoints, ndim=3):
  vec = np.random.randn(ndim, npoints)
  vec /= np.linalg.norm(vec, axis=0)
  return torch.from_numpy(vec)

class scp(object):
  """
  OPEN REVIEW VERSION:
  https://openreview.net/forum?id=BJge3TNKwH
  """
  def __init__(self, model: nn.Module, dataloader, L: int, device, prev_guards=[None]):
    self.model = model 
    self.dataloader = dataloader
    self.params = {n: p for n, p in self.model.named_parameters() if p.requires_grad}
    self._state_parameters = {}
    self.L= L
    self.device = device
    self.previous_guards_list = prev_guards
    self._precision_matrices = self.calculate_importance()
    for n, p in self.params.items():
      self._state_parameters[n] = p.clone().detach()
  
  def calculate_importance(self):
    precision_matrices = {}
    for n, p in self.params.items():
      precision_matrices[n] = p.clone().detach().fill_(0)
      for i in range(len(self.previous_guards_list)):
        if self.previous_guards_list[i]:
          precision_matrices[n] += self.previous_guards_list[i][n]

    self.model.eval()
    if self.dataloader is not None:
      num_data = len(self.dataloader)
      for data in self.dataloader:
        self.model.zero_grad()
        output = self.model(data[0].to(self.device))
          
        mean_vec = output.mean(dim=0)

        L_vectors = sample_spherical(self.L, output.shape[-1])
        L_vectors = L_vectors.transpose(1,0).to(self.device).float()
                    
        total_scalar = 0
        for vec in L_vectors:
          scalar=torch.matmul(vec, mean_vec)
          total_scalar += scalar
        total_scalar /= L_vectors.shape[0] 
        total_scalar.backward()     

        for n, p in self.model.named_parameters():                      
          precision_matrices[n].data += p.grad**2 / num_data      
              
    precision_matrices = {n: p for n, p in precision_matrices.items()}
    return precision_matrices

  def penalty(self, model: nn.Module):
    loss = 0
    for n, p in model.named_parameters():
      _loss = self._precision_matrices[n] * (p - self._state_parameters[n]) ** 2
      loss += _loss.sum()
    return loss
  
  def update(self, model):
    # do nothing
    return 

lll_lambda=100
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/151509.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Naive UI 组件使用体验之-级联选择 Cascader

使用场景 地址区域选择 简单使用 安装依赖 npm install naive-ui -D 按需引入之-手动引入 import {NCascader,CascaderOption } from naive-ui 使用 <n-cascader:value"regionValue":options"regionOptions":multiple"false"placehol…

一篇搞懂Python中的随机数

在 python 中生成随机样本的所有你需要的示例列表 长按关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 扫码关注《Python学研大本营》&#xff0c;加入读者群&#xff0c;分享更多精彩 在这篇博客中&#xff0c;我将演示如何根据不同的需求在python…

Docker三剑客——Docekr Swarm

目录 一、概述 二、Swarm 的核心概念 1. Node&#xff08;节点&#xff09; 2. Service&#xff08;服务&#xff09; 3. Task&#xff08;任务&#xff09; 三、Swarm 服务的运行部分 1. 工作节点 2. 服务、任务和容器 3. 任务和调度 4. 副本服务和全局服务 四、Swa…

3. 【prometheus 学习】prometheus数据类型

prometheus 四种数据类型学习及测试 安装 1&#xff09;从官网下载对应版本的二进制压缩包并解压 2&#xff09;新建prometheus.yml 文件&#xff0c;静态指定抓取本机的9091端口&#xff0c;设置采样时间2秒1次&#xff0c;方便一会测试。 scrape_configs:- job_name: defin…

单细胞UMAP图只标记特定细胞群、圈定细胞群及坐标轴修改

最近有小伙伴私信我&#xff0c;如下的单细胞UMAP图怎么做&#xff1f;是啥样的图呢&#xff1f;就是UMAP图上其他群是灰色的&#xff0c;只有某个群或者某几个群是标记颜色的&#xff0c;比较突出。其实很简单&#xff0c;一种办法可参考我们之前写过的ggplot做UMAP图&#xf…

uni-app使用蓝牙

目录 前言 连接蓝牙 开启蓝牙适配器 发现蓝牙 连接蓝牙 收发蓝牙数据 获取服务ID 获取特征值 读取蓝牙数据 写蓝牙数据 遇到的坑 获取serviceId的坑 特征值不支持读写 notify成功后立刻写蓝牙数据 工具方法 前言 原因是公司要搞个共享单车给内部员工使用&#…

32位浮点数表示方法

今天开始给大家介绍计算机组成原理课程&#xff0c;本文主要内容是32位浮点数表示方法。 一、32位浮点数构成 32位浮点数是计算机中常见的一种数据类型&#xff0c;该数占据32bit空间&#xff0c;可以表示较大范围内的整数和小数。32位浮点数由三部分组成&#xff0c;分别是符…

Java集合List、Set、Map底层源码解析

目录集合介绍MapHashMapLinkedHashMapHashTablePropertiesCollectionListArrayListVectorLinkedListSetHashSetLinkedHashSetTreeSet集合介绍 为什么使用集合&#xff1f; 当我们想要保存一组数据时&#xff0c;可以使用到的变量类型有集合和数组。那么就像说一下数组的局限性…

1.9

完善案例 ​ this.$nextTick(function () {this.$refs.input.focus()})}​ //点击编辑直接获取焦点 this.$refs.input.focus() //但是这种写法 由于input是用v-show控制的 所以执行了上面代码 改变了isEdit值 但是不会立马去重新解析模板 input框还没有出来 //将handleedit回调…

springboot+xxl-job初体验

在日常开发中经常遇到任务调度的需求&#xff0c;下面体验一下分布式调度xxl-job。 1、常见定时任务的实现方式 Java自带的java.util.Timer类ScheduledExcutorServiceSpringboot自带的EnableScheduling注解Quartz框架Elastic-job框架XXL-JOB框架 下面对xxl-job实现任务调度尝…

【TypeScript】TS进阶-函数重载(七)

&#x1f431;个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️作者简介&#xff1a;前端领域新星创作者、华为云享专家、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff…

一文读懂电商数字员工究竟是什么?| RPA铺第1期

百度的曦灵&#xff0c;中核的核小智、万科集团数字员工“崔筱盼”都曾在2022年度爆火&#xff0c;数字员工一夜之间成为众多行业追捧的对象&#xff0c;那么&#xff0c;他/她们究竟代表着什么&#xff0c;对企业而言&#xff0c;是噱头大于收益&#xff0c;还是收益大于噱头呢…

简单的客户端服务器(多线程)基于json通信

这是一个客户端和服务器通信的小项目&#xff0c;小编自己手写了一个json工具&#xff0c;测试比jsoncpp&#xff0c;protobuf "效率更高"&#xff08;浅拷贝&#xff09;&#xff0c;改写成深拷贝效率会急剧下降&#xff08;小编能力有限&#xff0c;知识点&#xf…

技术分享 | Spring Boot 异常处理

说到异常处理&#xff0c;我们都知道使用 try-catch 可以捕捉异常&#xff0c;可以 throws 抛出异常。那么在 Spring Boot 中我们如何处理异常&#xff0c;如何更优雅的处理异常&#xff0c;如何全局处理异常。是本章讨论解决的问题。Java 异常类首先让我们简单了解或重新学习下…

Android开发-AS学习(一)

完整项目最精简流程&#xff1a;Android <-> 接口 <-> 数据库Android开发工具&#xff1a;Android Studio项目目录信息&#xff1a;一、控件1.1 TextView基础属性描述layout_width组件的宽度layout_height组件的高度id为TextView设置一个组件idtext设置显示的文本内…

Linux 学习笔记(借鉴黑马程序员Linux课程)

Linux视频课程 简介 Linux诞生于1991年&#xff0c;由林纳斯托瓦兹在21岁时完成。此后成为最为流行的服务器操作系统之一。 Linux内核和系统发行版 由Linux系统内核和系统级应用程序两部分组成。 内核提供系统最核心的功能&#xff0c;如&#xff1a;调度CPU、调度内存、调…

【笑小枫的按步照搬系列】Redis多系统安装(Windows、Linux、Ubuntu)

笑小枫&#x1f495; 欢迎来到笑小枫的世界&#xff0c;喜欢的朋友关注一下我呦&#xff0c;大伙的支持&#xff0c;就是我坚持写下去的动力。 微信公众号&#xff1a;笑小枫 笑小枫个人博客&#xff1a;https://www.xiaoxiaofeng.com Windows 下安装 方式一&#xff1a;https…

HCL(新华三模拟器)如何连接CRT及改界面颜色

我使用的HCL版本是2.1.1官网下载连接&#xff1a;https://www.h3c.com/cn/Service/Document_Software/Software_Download/Other_Product/H3C_Cloud_Lab/Catalog/HCL/&#xff0c;一键直达下载官网这个版本可以适配virtualbox的5.2.44的版本&#xff0c;同时支持华为的ensp模拟器…

Spring Security 表单配置(一)

Spring Security 表单配置&#xff08;一&#xff09;工具版本及环境参考资源配置详细说明工具版本及环境 工具&#xff1a; IDEA 2021.3 Maven 3.8.6 JDK 8 Spring Boot 2.7.7 Spring Securiity 5.7.6 参考资源 Spring Security官网: https://docs.spring.io/spring-security…

javaEE 初阶 — 常见的锁策略

文章目录1. 乐观锁 vs 悲观锁2. 互斥锁 vs 读写锁3. 重量级锁 vs 轻量级锁4. 自旋锁 vs 挂起等待锁5. 公平锁 vs 非公平锁6. 可重入锁 vs 不可重入锁7. synchronized 是哪种锁8. 相关面试题1. 乐观锁 vs 悲观锁 乐观锁 指的是预测锁竞争不是很激烈&#xff0c;也就是指这里做的…