java多线程

2 篇文章 0 订阅

JMM java memory model java内存模型

volatile

cpu频率比内存条快,所以搞了个L1、L2、L3缓存,批量更新缓存。多个cpu之间遵守缓存一致性协议。

缓存一致性协议失效场景:

1.如果数据的长度超过缓存行,这种只能加总线锁。

2.cpu本身并不支持缓存一致性协议。

线程分为用户级线程和内核级线程

用户空间分为内核空间和用户空间

JMM围绕原子性、有序性、可见性展开

jvm进程他去申请的空间大部分时候是逻辑空间,不是物理空间。

逻辑空间是由我们系统已经划分好的

线程里有工作内存,工作内存映射到主内存,改完变量后刷新到主内存

JMM——Java内存模型 (juejin.cn)

(39条消息) JMM概述_牧竹子-CSDN博客_jmm

主要就是为了屏蔽平台的差异性

第三节116

a线程用一个变量去死循环,死循环有可能占用所有的资源,b线程去改这个变量,不加volatile,有可能b线程一直获取不到资源执行不到,导致变量一直不更新。a线程有机会让出锁就不会,加volatile实时更新,不加有可能执行几次才更新过来。

多个线程i++ 出问题就是因为多个线程的工作内存和主内存做同步

指令不能重排序的时候需要加个标记,这个标记就叫内存屏障

sychronized包的代码块也有可能指令重排

共享可变的资源叫临界资源

加锁为了序列化的访问临界资源

方法上 加static再用synchronized 是加锁在类对象上。

不加static,则加锁加在当前类对象上,这个类必须是单例。

(39条消息) 多线程:synchronized 关键字用法(修饰类,方法,静态方法,代码块)_萨达哈鲁的博客-CSDN博客_synchronized修饰类

synchronized修饰静态方法锁对象.class 这个类所有静态synchronized方法都互斥。修饰非static方法,锁的是对象,new不同对象是不会互斥的。

监视器锁是一个重量级锁,和synchronized修饰方法不同。

实例对象不一定存在堆内存上,如果实例对象没有线程逃逸行为,可能就在线程栈上开辟一段内存。

逃逸分析的博客:(39条消息) 别让Java对象逃逸(Object Escape)_wolfcode_cn的博客-CSDN博客_java 对象逃逸

jps 看进程 然后jmap -histo pid 看内存占用

对象逃逸分析 算是jvm的一个优化

用最通俗的语言解释Synchronized原理以及偏向锁,自旋锁,轻量级锁和重量级锁的区别 - 知乎 (zhihu.com)

synchronized为什么没有reteenlock性能好,synchronized还带自旋

(39条消息) 深入理解Java中的逃逸分析_HollisChuang’s Blog-CSDN博客_逃逸分析

AQS框架

lock属于互斥锁,countdownlatch属于共享锁还有信号量和栅栏

rentrentlock 是悲观锁

独占锁是悲观锁,共享锁是乐观锁

哪些锁是不可重入的

公平锁与非公平锁

clh队列

如果node在条件队列中,node必须是独占模式,不能是共享。主要是blockqueue

lock锁能加两次 解两次

semphore 默认创建非公平锁

atomic类依赖unsafe类来实现原子操作

directybuffer直接是操作堆外内存。queue能不能用这个? 估计不安全吧

jdk1.7 hashmap 死锁问题

红黑树是什么

java并发编程实战

单核cpu也支持多线程 因为有阻塞,可以让用户感觉到多个程序在执行,用户体验度高。多核心cpu是可以真的实现并行。

创建线程的方法 :

Runnable接口、 thread 类(runnable)的实现类、callable future、executor框架(ThreadPool)

线程池最好自定义factory去指定线程池的名字,方便看日志。

线程终止 不建议使用stop 类似kill -9 建议 interrupt()方法 这个还能唤醒线程 interruped()复位 回到初始状态,interrupt会改一个isinterrrupted的属性,判断这个属性做业务的处理。

线程好处 压榨cpu 性能好 劣势:共享资源容易出问题 会有线程安全的问题

Sychronized 重量级锁 修饰 方法 代码块 静态方法 锁的级别不一样 sychronized 类.class会把整个类锁住 锁粒度怎样控制 性能才会好

1.6之前 sychronized是重量级锁 1.6之后

无锁、 偏向锁 、轻量级锁 、重量级锁(真正意义上的锁)

加入两个线程A和B 有三种情况

1 只有A线程去访问(大多数情况是这种,没必要加锁 用偏向锁) 记录线程id和锁标记 这种用的少 一般都在关着 优化

2 A和B线程交替访问(用轻量级锁)自旋锁

# 多个线程同时访问(只能阻塞了)

偏向锁

cas比较 实现原子性 是一种乐观锁 compare and swap

在数据库实现乐观锁 通过version字段去控制

自旋锁

cas一直循环比较

绝大多数线程在使用锁以后 会在非常短的时间内释放锁 在这种情况下 线程一直循环 比阻塞线程 线程挂起要快 性能要好 但是超过一定时间 就只能挂起了 升级成重量级锁 有一个平衡点(设置自旋次数 preBlockSpin 默认十次 jdk1.6后可以自适应自旋)

重量级锁

升级到重量级锁之后 没有获得锁的线程会阻塞 进入block状态 通过监视器实现 javap -v 命令

互斥锁 基于操作系统 Objectmonitor

偏向锁和轻量级锁 并没有真正的加锁,偏向锁基于cas 轻量级锁基于自适应自旋锁 自旋cas,偏向锁一般是关闭的 场景少 需要了可以自己开

Sychronized 把几个锁都封装了 自动升锁 锁只能升级 不能降级

偏向锁只有撤销 没有释放

全局安全点(没有线程在执行的时候) 批量撤销 :epoch 进行升级epoch的值 下一次再访问这个锁 会对比数字 对不上 会撤销 并且重新偏向

wait会释放锁和cpu资源 sleep不会释放锁但是会释放cpu资源

实现线程安全就是加锁

锁升级的过程没自旋锁吗 ??

偏向锁 cas、 轻量级锁 自旋锁 、 重量级 mutux

---------------------------------------------------------------------------

volatile

保证共享变量可见性

原理 hsdis 多了一个Lock的汇编指令 lock(缓存锁) 达到内存屏障 从而达到可见性

什么是可见性:

Cpu、内存、io设备 最大性能取决于最大的短板 木桶原理

硬件层面

最大利用cpu资源

1cpu增加高速缓存 cpu l2 l2 l3 同步到缓存 然后同步到主内存 这样会有缓存不一致问题

解决方案

总线锁(性能不好)

缓存锁(基于缓存一致性协议MESI 不同的cpu架构 实现不一样)MESI是四种状态

一个地方缓存修改 会让其他cpu的缓存失效

cpu重排序 缓存更新与数据更新 不一定哪个先执行

解决这个问题 cpu提供了一个指令 内存屏障 内存屏障用来解决可见性问题

cpu提供了三种屏障

写屏障 读屏障 全屏障

Store barrier load barrier full barrier

内存屏障和重排序和平台以及硬件有关系

2引入线程进程概念 阻塞了线程 执行别的

2 指令的优化 体现在指令重排序

jmm****层面

导致可见性问题的根本原因是 高速缓存 和重排序

如何解决可见性:

jmm 最核心的价值 提供了有序性和可见性

Jmm **(编译器)**语言级别的抽象内存模型(抽象)

有主内存 和工作内存的概念

volatile sychronized 、final、happen-before 去解决可见性问题

除了cpu重排序(指令集和内存) 还有编译器的重排序 最后变成可执行的指令

不是所有的程序都会重排序

根据数据依赖规则

as-if serial 不能改变单线程的执行结果

可见性保障除了volatile还有其他方法

A happens-before B

final是hanppens-before原则

join是不是 还有wait sleep

哪些操作会建立happens-before原则

volatile只是可见性 不解决原子性

Sychronized 解决原子性 有序性 可见性

对象逃逸

Condition

countdownlatch

Semaphore 可以做限流

Cyclicbarrier 栅栏 可以使一组线程达到同步点之前阻塞 这样可以同时启动多个线程好像

Condition await 阻塞 signal唤醒 signalall唤醒所有

Condition await 会调用aqs里的await

Condition 方便些生产者消费者模式

countdownlatch

使用场景:计数器

Await/countdown

会用到AQS的共享锁

静态方法 加sychronized 锁的是这个类

活锁: 俩线程互相谦让 都不执行,解决方法1 争夺资源的时候加随机的sleep时间 。2 约定线程优先级

JMM java memory model java内存模型

volatile

cpu频率比内存条快,所以搞了个L1、L2、L3缓存,批量更新缓存。多个cpu之间遵守缓存一致性协议。

缓存一致性协议失效场景:

1.如果数据的长度超过缓存行,这种只能加总线锁。

2.cpu本身并不支持缓存一致性协议。

线程分为用户级线程和内核级线程

用户空间分为内核空间和用户空间

JMM围绕原子性、有序性、可见性展开

jvm进程他去申请的空间大部分时候是逻辑空间,不是物理空间。

逻辑空间是由我们系统已经划分好的

线程里有工作内存,工作内存映射到主内存,改完变量后刷新到主内存

JMM——Java内存模型 (juejin.cn)

(39条消息) JMM概述_牧竹子-CSDN博客_jmm

主要就是为了屏蔽平台的差异性

第三节116

a线程用一个变量去死循环,死循环有可能占用所有的资源,b线程去改这个变量,不加volatile,有可能b线程一直获取不到资源执行不到,导致变量一直不更新。a线程有机会让出锁就不会,加volatile实时更新,不加有可能执行几次才更新过来。

多个线程i++ 出问题就是因为多个线程的工作内存和主内存做同步

指令不能重排序的时候需要加个标记,这个标记就叫内存屏障

sychronized包的代码块也有可能指令重排

共享可变的资源叫临界资源

加锁为了序列化的访问临界资源

方法上 加static再用synchronized 是加锁在类对象上。

不加static,则加锁加在当前类对象上,这个类必须是单例。

(39条消息) 多线程:synchronized 关键字用法(修饰类,方法,静态方法,代码块)_萨达哈鲁的博客-CSDN博客_synchronized修饰类

synchronized修饰静态方法锁对象.class 这个类所有静态synchronized方法都互斥。修饰非static方法,锁的是对象,new不同对象是不会互斥的。

监视器锁是一个重量级锁,和synchronized修饰方法不同。

实例对象不一定存在堆内存上,如果实例对象没有线程逃逸行为,可能就在线程栈上开辟一段内存。

逃逸分析的博客:(39条消息) 别让Java对象逃逸(Object Escape)_wolfcode_cn的博客-CSDN博客_java 对象逃逸

jps 看进程 然后jmap -histo pid 看内存占用

对象逃逸分析 算是jvm的一个优化

用最通俗的语言解释Synchronized原理以及偏向锁,自旋锁,轻量级锁和重量级锁的区别 - 知乎 (zhihu.com)

synchronized为什么没有reteenlock性能好,synchronized还带自旋

(39条消息) 深入理解Java中的逃逸分析_HollisChuang’s Blog-CSDN博客_逃逸分析

AQS框架

lock属于互斥锁,countdownlatch属于共享锁还有信号量和栅栏

rentrentlock 是悲观锁

独占锁是悲观锁,共享锁是乐观锁

哪些锁是不可重入的

公平锁与非公平锁

clh队列

如果node在条件队列中,node必须是独占模式,不能是共享。主要是blockqueue

lock锁能加两次 解两次

semphore 默认创建非公平锁

atomic类依赖unsafe类来实现原子操作

directybuffer直接是操作堆外内存。queue能不能用这个? 估计不安全吧

jdk1.7 hashmap 死锁问题

红黑树是什么

9 .8.29

多线程优势:

1 资源利用率高 cpu在阻塞的同时可以先执行别的程序

2 公平性 用户计算机的程序能够共享计算机资源

3 便利性 每个程序执行一个任务

快 异步 用户体验好 发挥处理器性能

多线程风险:

1 安全性问题 访问共享变量可能会出问题

2 线程死锁

3 频繁上下文切换降低性能

sychronized是一种独占式的锁 ?

线程安全性:不管怎样 这个类都表现出正确的行为

原子性:独立的操作 不可分割 i++ 读取 修改 写入

竞态条件 :不恰当的执行顺序 出现了错了结果

不可变对象一定是线程安全的 一定不会有线程安全的问题

第一章 简介

多线程用户体验度好 能发挥cpu的性能 但是容易带来线程安全的问题 和死锁问题。

第二章 线程安全性

怎样避免线程安全问题

1 不在线程直接共享变量

2 将共享变量改为不可变的

3 在访问共享变量时同步

什么是线程安全性

当多线程访问某个类时,这个类始终都鞥呢表现出正确的行为,这个类就是线程安全的。

无状态对象一定是线程安全的 springmvc 的请求就属于无状态的

原子操作

对于访问同一个状态的所有操作 都是在一个操作里 也就是一个原子操作

当在不变性条件中涉及多个变量时,各个变量之间并不是彼此独立的,而是某个变量的值会对其他变量的值产生约束。

因此 当更新某一个变量时,需要再同一个原子操作中对其他变量进行同事更新。

内置锁 又称为监视器锁 应该指的就是sychronized

重入锁 线程获得了锁 再调用加锁的方法可以直接进去

复合操作中加一个锁 可以变成原子操作

每个共享的和可变的变量 都应该只有一个锁保护,用的乱了不好。用了锁就不要用原子变量 atomicInteger

如果将每个方法都作为同步方法 比如vector 那么并不能保证vector上的复合操作都是原子性的。

执行长时间计算或者可能无法快速完成的操作时(网络io 控制台Io) 一定不要持有锁。

第三章 对象的共享

在没有同步的情况下,编译器、处理器以及运行时等都可能对操作的执行顺序进行重排序

非volatile类型的64位数值变量(double和long) jvm允许将64位的读操作或者写操作分解为两个32位的操作 所以要用锁 或者volatile声明 AtomicLong应该也行

最低安全性: 线程没有同步的情况下,拿到了之前某个线程设置的值。

多个线程访问某个共享可变变量的时候要求所有线程在同一个锁上同步,就是为了可见性。

加锁保证互斥行为 和可见性。

Volatile 弱同步机制 不会被重排序 而且总能看到最新的值 加锁保证了护持行为 和可见性 volatile只能保证可见性 不能保证原子性 比如i++ 读-改-写

this溢出

ThreadLocal

ThreadLocal能维持线程封闭性

ThreadLocal提供了get与set等访问接口 或者方法,这些方法为每个使用该变量的线程都存有一份独立的副本。

final与不可变对象之间的关系

怎样安全的发布对象 书写的不好

第四章 对象的组合

在对象内定义一个属性 锁的时候用 这个叫做监视器模式

Private final Object obj=new Object();

多个接口操作****list 锁也要加在list

第五章 基础构建模块

Concurrenthashmap 源码 这个组合操作不用加锁 同步容器需要加锁 为什么

并发容器比同步容器性能好为什么

Copyonwritearraylist 当迭代操作远远大于修改操作的时候才考虑
java 有界队列 无界队列

Queue Deque

同步工具类

闭锁:Latch Futuretask

闭锁是一次性对象 终止就不能重置。

闭锁是一种同步工具类,可以延迟线程的进度 直到到达终止状态。闭锁的作用相当于一扇门:在闭锁到达结束状态之前,这扇门一直是关闭的,

并且没有任何线程能通过,当到达结束状态时,这扇门会打开丙允许所有的线程通过。当闭锁到达结束状态后,将不会再改变状态。闭锁可以确保

某些活动知道其他活动都完成户才继续执行:

\1. 面试题 同时启动500个线程

  1. 确保资源都初始化再执行
  2. 确保服务在其依赖的所有服务都启动好之后再启动

Countdownlatch 可以实现所有线程同时开启 等待到最后一个关闭

countdown方法会一直减数字 await方法会一直阻塞到计数器为0. 或者线程中断或者超时

FutureTask future.get 如果任务已经执行完成 会立即返回结果 ,否则get将阻塞直到任务进入完成状态,然后返回结果。futuretask会提前启动

信号量 semaphore 用来控制操作某个特定资源的操作数量,比如线程池。BlockingQueue做线程池更简单。

栅栏 barrier和Exchanger

类似闭锁 能阻塞一组线程直到某个事件发生。

Cyclebarrier 可以使一定数量的参与方反复地在栅栏位置汇集,它在并行迭代算法中非常有用,可以将一个问题拆分为一系列相互独立的子问题。

当线程到达展览位置时将调用await方法 这个方法将阻塞直到所有线程都到达栅栏位置,然后栅栏会打开 释放所有线程。栅栏会重置以便下次使用。

另一种是交换数据 两个线程向缓冲区 一个写 一个读 。

使用场景:

barrier主要是分割成子线程

Exchanger 两个线程 一个读一个写

栅栏和闭锁的区别: 栅栏能重置重复利用 闭锁只能使用一次 不能重置。

第六章 任务执行

Executor框架 基于生产者消费者模式 提交是生产者 执行是消费者。

一组任务依赖另一组任务的结果的时候 不知道哪一组任务执行的快,这种情况 适合用CompletionService

completionService 是将Executor和BlockingQueue的功能融合在一起

future的get方法可以设置超时时间 超过一定时间不再需要它的结果的情况下会有用。

invokeall方法也可以控制超时

第七章 取消与关闭

为什么需要任务取消:

1用户去掉 点击了按钮

2 有时限的操作 比如 搜索一定时间内搜不到就不搜了

3 应用程序事件 当其中一个任务找到解决方案的时候 其他任务都会被取消

4 错误 比如爬虫爬满了磁盘 所有搜索任务会去掉 这时候可能记录它们的当前状态,以便稍后重新启动。

5 关闭 关闭程序的时候

调用interrupt并不意味着立即停止目标线程正在进行的工作,而只是传递了请求中断的消息。

对中断的正确理解是:

它并不会真正的中断一个正在运行的线程,而只是发出中断请求,然后由线程在下一个合适的时刻中断自己(这个时刻也被称为取消点)

Interrupted 会清楚当前线程的中断状态。

一般中断是取消线程的最合理的方式

处理不可中断的阻塞

发生场景:

如果一个线程由于执行同步的Socket IO 或者等待获得内置锁而阻塞,那么中断请求只能设置线程的中断状态,除此之外没啥用。

比如 同步socket io 异步io 获取某个锁

这种可以改写interrupt方法 线关闭io 再调用原来的interrupt方法。

newTaskFor也可以

关闭****ExecutorService

1 shutdown 正常关闭

2shutdownnow 强制关闭

在进行强制关闭时,shutdownnow首先关闭当前正在执行的任务,然后返回所有尚未启动的任务清单。

差别:

安全性和响应性

强制关闭速度更快,但风险也大,因为任务可能执行到一半的时候被结束;

正常关闭速度虽然慢 但是更安全,因为executorservice会一直等到队列中所有的任务都执行完成后才关闭。

毒丸对象

只有在无界队列中 毒丸对象才能可靠的工作。

守护线程:

jvm启动时创建的线程 除了主线程 其他的都是守护线程 比如垃圾回收器

jvm停止的时候 所有守护线程会被抛弃 不会执行finally

Finalize 终结器 尽量不要用

关闭线程

Thread.interrupt ,future.cancel(true)

Executor 最后也要关闭 不然jvm不能正确关闭****executorservice.shutdown shutdownnow

线程分为普通线程和守护线程

垃圾回收器就是守护线程

默认的 主线程创建的所有线程都是普通线程

第八章 线程池的使用

饥饿死锁:

一个线程依赖另一个线程

多线程入门

场景 需求 解决方案 怎样用 什么原理

干啥的 怎样用 什么原理 有什么坑

单核cpu也支持多线程 因为有阻塞

单核cpu只能因为阻塞 切换 来提高性能 多核心cpu是可以真的实现并行

创建线程的方法 :

Runnable接口、 thread 类(runnable)的实现类、callable future、executor框架(ThreadPool)

最好多用线程池

使用场景:

文件跑批 收益文件 对账文件还有bio模型的优化

并发基础:

生命周期:

线程一共有6种状态 thread代码里有

创建到销毁的流程 new 通过start方法— runnable(运行状态)分为就绪状态和运行中状态------ terminated(终止)

写线程一定要写名称 方便看日志

hostport****源码有时间拉取下来看看

线程启动是start 调用虚拟机的方法

线程终止 不建议使用stop 类似kill -9 建议 interrupt()方法 这个还能唤醒线程 interruped()复位 回到初始状态

第二种 异常情况:

中断出去阻塞状态的线程会报interrupedexception 报错也会复位 然后会继续执行 throw这个错 也会让线程终止复位

Sychronized 锁定的对象只能是不可变的object 不能是integer和int和string常量 直接private吧 最好了

第二课

akka用的纤程 比线程效率还要高

Volitale 就是禁止指令重排序 保证线程可见性

sychronized不能阻止重排序 阻止重排序干嘛呢?

aba问题 加版本号 有版本号这个类 atomicstampedreference 或者加标签

第三课 13分钟

Cas为什么比加锁快? 加锁也有锁升级 默认也是cas sychronized 估计lock不是

lock直接是重量级锁 可能默认10次升级锁不合理吧

longader与atomiclong有什么区别?

longader是分段锁

Reteenlock new的时候传入true 可以成为公平锁

Cycylbarrier 可以同时开启多个线程 必须多个线程同时到位了 才能开始执行

countdownlatch· 可以让线程都执行完再往下走 future也行

Semphore 信号量 可以限流 同时只能有多少个 ,也可以搞成公平的 传个参数

Phaser 这个要看看

Readwritelock 其实就是共享锁和排它锁 读的时候共享锁 写的时候排他

共享锁与重入锁 有冲突没

Exchanger 类 线程交换数据

第四课 spring ioc

Spring mvc 在spring里 spring在spring boot里?

java线程模型

Java 多线程与操作系统多线程的区别:

java多线程 native方法调到jvm的c++代码,c++又调用了操作系统的方法

C、c++ 操作系统,晚点都学学吧 还有python 简单了解一下

java的锁依赖操作系统的锁

start怎样调用的run方法:

start掉操作系统,操作系统调run

公平锁与非公平锁:

线程的一些迷惑行为和指令重排序有关系

为什么优化sync 不是因为重,重量级锁是互斥,不需要互斥,sync也是偏向锁的实现,只有一个线程 那就是偏向锁,而不是互斥锁,以前应该是没实现偏向锁。

偏向锁不会调用os函数的实现

Volatile 线程可见性、禁止cpu重排序

java内存模型与cpu的内存模型不一样

Volatile 只保证可见性,i=100两个线程同时拿到 都加1 一个还没执行完,另一个加1 结果 101出现两次。volatile没有保证原子性。、

atomic保证原子性,可见性呢?

多个atomic类一起运算能不能保证原子性,不能吧 不是一个锁

公平锁 设置个true ,是绝对公平的吗?

sync加在static方法上 锁的是类对象

守护线程,所有线程都结束了,他也自己结束了? 设置不设置有什么区别呢?

设置必须在start方法之前设置 有什么用吗?

Threadlocal

queue与list有啥区别 ,为啥queue用的那么少

有一个想法,大多数的api都要玩一下 先知道api,后面看源码怎么实现的

jdk所有的文件干啥的 都搜一下

concurrenthashmap与hashtable的区别 哪个快 都怎么实现的 ,map一定比table好吗

深入java虚拟机 对象头的图是错的?

Jvm启动的时候要开启很多同步方法,用偏向锁大部分要升级,所以默认把偏向锁关了,偏向锁在没有锁竞争的时候有用,有多个线程就锁升级了,所以默认偏向锁是延时开启的。?
锁膨胀过程:

偏向锁默认延迟4秒

processon 画图工具

Forkjoin

Jmm

Happed before

Akka

AQS

Sync 是jvm内部实现的 会调用操作系统底层

Lock 是基于jdk的 可以看源码,sync不能看到源码

9-1 后面没看了

看几本书 看看源码 和api 完全搞定吧,整理笔记,看视频用处不大

线程安全与锁优化

java中的线程安全

不可变

final关键字不可变的,线程安全的。安全的原因是final变量无法二次赋值,二次赋值会编译报错所以是安全的。哈哈哈 太傻逼了。

绝对线程安全

线程安全的容器也不是绝对的安全,只是相对安全。操作容器的多个方法上要加同一个锁(监视器锁,对象锁吧,没必要搞类锁)才能保证绝对安全。

相对线程安全

vector、hashtable、Collections.synchronizedCollection()包裹的集合都是这种。不要用,想保证安全自己加锁。太可怕了

线程安全的实现方法

互斥同步

lock比synchronized多的功能

1.等待可中断
2.可以实现公平锁,但是性能会急剧下降。synchronized和lock默认都是非公平的。公平锁是按锁的申请时间顺序拍获得锁。
3.绑定多个condition。

非阻塞同步

无锁 非阻塞同步 Non-Blocking Synchronization

基于冲突检测的乐观锁并发策略。
不管风险,先执行操作。如果没有其他线程争用共享数据,那操作就直接成功了。如果共享的数据的确被争用,产生了冲突,那再cas。

无同步方案

纯代码方法,方法里不改数据。
线程内部变量。
符合这两种不需要同步也ok。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值