原子

十、多线程控制类(1)

一笑奈何 提交于 2019-11-29 12:30:45
前言:   前面我们介绍了要想保证多线程变现过程中的安全问题,我们就要保证在读线程编写过程中保证多线程的三大特性,那么java为了保证多线程的三大特性引入了很多线程控制机制,下面就来介绍场用的几种。 一、ThreadLocal:    ThreadLocal线程本地变量,它可以为每一个线程刚保存一份线程内变量的副本,可以保证线程线程之间的变量时互不影响的,且是原子类可以保证变量的原子操作,当某些数据是以线程为作用域且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal。   ThreadLocal常用的方法:     initialValue:创建副本方发: (注:在jdk1.8引入了lambda构造方式,方法变成了withlnitial)     get:获取副本方法:     set:设置副本方法:   在这里我我们来模拟一下两个用户之间的转账,来看一下ThreadLocal的实现: public class ThreadLocalDemo { //创建一个银行账户:账户有存款,可以进行存钱取钱操作。 static class Bank{ private ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> { return 0; //假设我们每个人的账户初始余额都是零 }); /

java.util.concurrent.atomic原子操作类包

杀马特。学长 韩版系。学妹 提交于 2019-11-29 06:42:26
这个包里面提供了一组原子变量类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。可以对基本数据、数组中的基本数据、对类中的基本数据进行操作。原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读-改-写操作。 java.util.concurrent.atomic中的类可以分成4组: 标量类(Scalar):AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference 数组类:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray 更新器类:AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater 复合变量类:AtomicMarkableReference,AtomicStampedReference 第一组AtomicBoolean,AtomicInteger

我大概知道他在说什么了,是对内存单元的竞争访问吧。Python有GIL,在执行伪码时是原子的。但是伪码之间不保证原子性。 UDP丢包,你是不是做了盲发?没有拥塞控制的情况下,确实会出现丢包严重的情况。你先看看发送速率,还有是否带有拥塞控制。

最后都变了- 提交于 2019-11-28 22:22:13
我大概知道他在说什么了,是对内存单元的竞争访问吧。Python有GIL,在执行伪码时是原子的。但是伪码之间不保证原子性。 UDP丢包,你是不是做了盲发?没有拥塞控制的情况下,确实会出现丢包严重的情况。你先看看发送速率,还有是否带有拥塞控制。 https://groups.google.com/forum/#!topic/python-cn/Vivn--4LfGM 来源: https://www.cnblogs.com/yuanjiangw/p/11430179.html

并发编程-CAS

泄露秘密 提交于 2019-11-28 21:43:09
CAS (compareAndSwap),中文叫比较交换,一种 无锁原子算法 。 过程是这样:它包含 3 个参数 CAS(V,E,N),V表示要更新变量的值,E表示预期值,N表示新值。仅当 V值等于E值时,才会将V的值设为N,如果V值和E值不同,则说明已经有其他线程做两个更新,则当前线程则什么都不做。最后,CAS 返回当前V的真实值。CAS 操作时抱着乐观的态度进行的,它总是认为自己可以成功完成操作。 CAS是一条CPU的原子指令,其作用是让CPU先进行比较两个值是否相等,然后原子地更新某个位置的值,其实现方式是基于硬件平台的汇编指令,在intel的CPU中,使用的是cmpxchg指令,就是说 CAS是靠硬件实现的 ,从而在硬件层面提升效率。 当多个线程同时使用CAS 操作一个变量时,只有一个会胜出,并成功更新,其余均会失败。 失败的线程不会挂起 ,仅是被告知失败,并且允许再次尝试,当然也允许实现的线程放弃操作。基于这样的原理,CAS 操作即使没有锁,也可以发现其他线程对当前线程的干扰。 与锁相比,使用CAS会使程序看起来更加复杂一些,但由于其非阻塞的,它对死锁问题天生免疫,并且,线程间的相互影响也非常小。更为重要的是,使用无锁的方式完全没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销,因此,他要比基于锁的方式拥有更优越的性能。 简单的说,CAS 需要你额外给出一个期望值

原子性操作类AtomicInteger

夙愿已清 提交于 2019-11-28 18:05:24
来由: 对于Java中的运算操作,例如自增或自减,若没有进行额外的同步操作,在多线程环境下就是线程不安全的。 private static final AtomicInteger count = new AtomicInteger(); count.incrementAndGet();    来源: https://www.cnblogs.com/otways/p/11418125.html

串烧 JavaCAS相关知识

旧巷老猫 提交于 2019-11-28 16:25:10
JMM与问题引入 为啥先说JMM,因为CAS的实现类中维护的变量都被volatile修饰, 这个volatile 是遵循JMM规范(不是百分百遵循,下文会说)实现的保证多线程并发访问某个变量实现线程安全的手段 一连串的知识点慢慢缕 首先说什么是JMM, JMM就是大家所说的java的内存模型, 它是人们在逻辑上做出的划分, 或者可以将JMM当成是一种规范, 有哪些规范呢? 如下 可见性: 某一个线程对内存中的变量做出改动后,要求其他的线程在第一事件内马上马得到通知,在CAS的实现中, 可见性其实是通过不断的while循环读取而得到的通知, 而不是被动的得到通知 原子性: 线程在执行某个操作的时,要么一起成功,要么就一起失败 有序性: 为了提高性能, 编译器处理器会进行指令的重排序, 源码-> 编译器优化重排 -> 处理器优化重排 -> 内存系统重排 -> 最终执行的命令 JVM运行的实体是线程, 每一个线程在创建之后JVM都会为其创建一个工作空间, 这个工作空间是每一个线程之间的私有空间, 并且任何两条线程之间的都不能直接访问到对方的工作空间, 线程之间的通信,必须通过共享空间来中转完成 JMM规定所有的变量全部存在主内存中,主内存是一块共享空间,那么如果某个线程相对主内存中共享变量做出修改怎么办呢? 像下面这样: 将共享变量的副本拷贝到工作空间中 对变量进行赋值修改

并发编程-java内存模型

十年热恋 提交于 2019-11-28 13:44:14
1. 基本概念   程序:静态,用于完成某些功能的代码。   进程:动态,运行中的程序   线程:进程中的实际运作单位,一个进程可以包含一个或多个线程。 2. JVM内存区域 堆:线程共享,存放实例对象 (OOM) 虚拟机栈 :线程私有 ,Java方法在运行时的内存模型 (OOM),存放局部变量、引用类型数据的地址、操作数栈 本地方法栈 方法区 : 线程共享,存放类信息,常量,静态变量等 程序计数器 : 线程私有, 存放下一条指令的地址 3. java内存模型(java memory model, JMM,抽象的模型) 作用: 规范内存空间和工作空间数据的交互 主内存: 线程共享的信息 工作内存:线程私有的信息。基本数据类型,直接分配到工作内存。引用的地址存放在工作内存,引用的对象存放在堆中。 工作方式:   线程修改私有数据,直接在工作空间改   线程修改共享数据,把数据复制到工作空间中,在工作空间中修改,修改完成后,刷新到内存。 4. 硬件内存架构 CPU缓存一致性问题的解决方案: 1. 总线加锁 : 降低CPU的吞吐量 2. 缓存上的一致性协议 当CPU在CACHE中操作数据时,如果该数据是共享变量,数据在CACHE读到寄存器中,进行新修改,并更新内存数据 CaCHE LINE置无效,其他的CPU就从内存中读数据 5. java线程与硬件处理器 6. 并发编程的三个特性

volatile关键字浅析

风格不统一 提交于 2019-11-28 13:01:43
volatile关键字浅析 在并发编程中,volatile是很常用的一个修饰符。JDK官方文档是这么形容volatile的: The Java programming language provides a second mechanism, volatile fields, that is more convenient than locking for some purposes. A field may be declared volatile, in which case the Java Memory Model ensures that all threads see a consistent value for the variable. 这里意思很明白,volatile在某些用途下比锁更方便,一个变量被声明为volatile,jvm能够保证所有的线程都看到的是一致的变量,也就说一个线程对一个共享变量修改,其他线程能够立即看到最新的值。 volatile在某些情况下可以代替锁,比synchronized成本和开销更低,因为不会引起线程的上下文切换,为什么上下文切换就会开销比较大,因为原来缓存的指令和数据都没用了,要重新加载指令和数据到缓存中,你说开销大不大。 1.首先看看可见性 volatile修饰的共享变量,当该变量发生写操作时,把该变量刷新到内存中

浅析Volatile关键字

跟風遠走 提交于 2019-11-28 12:56:48
浅析Volatile关键字 在java中线程并发中,线程之间通信方式分为两种:共享内存和消息传递。共享内存指的是多个线程之间共享内存的属性状态;消息传递指的是线程之间发送信息来通信。在介绍volatile,我们先了解一下共享内存一些基本概念。 JMM Java内存模型(简称JMM)控制线程通信,可以分为主内存和本地内存,每个线程拥有一个本地内存。 如图,一般主存只有一个,根据线程数不同,本地内存(又称工作内存)数目也不同,本地内存是抽象出来的概念,实际上不存在。 线程之间通过内存来同步状态可以分为以下几个步骤: 1、 线程1从主存获取变量x=1,假设此时其他线程x都为1 2、 线程1将本地内存中x值修改为2 3、 线程1将本地内存中x值放回主存 4、 其他线程同步主存数据 以上,就是理想状态线程之间通过主存通信状态,保证了内存的 可见性 。 指令重排序 java程序在运行时,并不会严格按照程序代码编写的顺序执行代码,会对其进行重排序。例如以下例子: 在程序执行代码的时候,步骤1和步骤2可能被重排序,导致2可能在1之前先执行,但是重排序的前提是 在单线程情况下不会改变运行结果, 因此1和2可以重排序,但是3引用了1和2中的变量,因此3不会被重排序到1或者2之前。在单线程情况下,重排序不会影响,但在多线程中会导致结果不可预见,可以使用其他方法来保证 有序性 。 原子性操作 前面提到了

Java Automic包下的AtomicInteger

人走茶凉 提交于 2019-11-28 08:13:06
感谢这两位博主的文章,文章源于: https://www.cnblogs.com/chenpi/p/5375805.html https://blog.csdn.net/fanrenxiang/article/details/80623884 版本:dk1.5后提供了,java.util.concurrent.atomic包 作用:方便程序员在多线程环境下,无锁的进行原子性操作 底层:原子变量的底层使用了处理器提供的原子指令,但是不同的CPU架构可能提供的原子指令不一样,也有可能需要某种形式的内部锁,所以该方法不能绝对保证线程不被阻塞 内部核心:Atomic包里内部实现不是简单的使用synchronized,而是一个更为高效的方式CAS (compare and swap) + volatile和native方法(同步的工作更多的交给了硬件),从而避免了synchronized的高开销,执行效率大为提升 关于CAS: compare and swap,比较和替换技术,将预期值与当前变量的值比较(compare),如果相等则使用新值替换(swap)当前变量,否则不作操作; 现代CPU已广泛支持CAS指令,如果不支持,那么JVM将使用自旋锁,与互斥锁一样,两者都需先获取锁才能访问共享资源,但互斥锁会导致线程进入睡眠,而自旋锁会一直循环等待直到获取锁; 另外