线程

volatile 手摸手带你解析

不打扰是莪最后的温柔 提交于 2020-03-25 11:01:03
前言 volatile 是 Java 里的一个重要的指令,它是由 Java 虚拟机里提供的一个轻量级的同步机制。一个共享变量声明为 volatile 后,特别是在多线程操作时,正确使用 volatile 变量,就要掌握好其原理。 特性 volatile 具有 可见性 和 有序性 的特性,同时,对 volatile 修饰的变量进行单个读写操作是具有 原子性 。 这几个特性到底是什么意思呢? 可见性: 当一个线程更新了 volatile 修饰的共享变量,那么任意其他线程都能知道这个变量最后修改的值。简单的说,就是多线程运行时,一个线程修改 volatile 共享变量后,其他线程获取值时,一定都是这个修改后的值。 有序性: 一个线程中的操作,相对于自身,都是有序的,Java 内存模型会限制编译器重排序和处理器重排序。意思就会说 volatile 内存语义单个线程中是串行的语义。 原子性: 多线程操作中,非复合操作单个 volatile 的读写是具有原子性的。 可见性 可见性是在多线程中保证共享变量的数据有效,接下来我们通过有 volatile 修饰的变量和无 volatile 修饰的变量代码的执行结果来做对比分析。 无 volatile 修饰变量 以下是没有 volatile 修饰变量代码,通过创建两个线程,来验证 flag 被其中一个线程修改后的执行情况。 /** * Created

python多线程完成模拟支付请求

本秂侑毒 提交于 2020-03-25 09:27:50
import asyncioimport sysfrom queue import Queuesys.path.append("../")from tool.__init__ import *from tool.decorator_token import *import timefrom threading import Thread,Lockclass doWeChatNotify(BaseTest): def __init__(self): super().__init__() self.limit_num=100 #查询记录条数 self.WeChatNotify_sql='''select order_id,order_sn from fw_order where `status`=0 and course_id=1569 ORDER BY create_time desc limit %d ;'''%(self.limit_num) self.fwh_test_api=fwh_test_api self.data = self.my_op.sql_operation_fwh(self.WeChatNotify_sql) self.fwh_order_dict = {} self.que = Queue() @token_fwh#验证token有效性 def get

线程概念

百般思念 提交于 2020-03-25 06:57:06
## 线程多线程基础了解 ### 什么是线程,什么是多线程,线程和进程的区别,为什么要有多线程? 线程是cpu执行任务的最小单位 一个进程有1到n的线程组成,比如我们常用的编辑工具打开后就是一个进程,而这个进程就是由多个线程组成 ### 为什么要有线程? 因为线程可以把执行时间长的任务交给后台处理,可以大大节省时间,使程序使用率大大提高 比如我们在处理一个业务时,有一个任务其实对返回结果没有影响,但是执行时间比较长又不得不处理,这里我们就可以用线程,把这个任务交给线程去执行,这样就大大节约了 时间提高了效率 ### 既然有了线程为什么要有多线程呢? 因为有时候任务量太多,可能一个线程处理不过来,这样就可以用多个线程同时处理这样就可以提高效率 比如你开了家餐馆,那么客人来了肯定要做菜,但是你一个人肯定忙不过来,那么就请了两个伙计,一个伙计去买菜,一个伙计去做其他准备工作,你直接负责分配任务就好了,这样 任务就能快速完成 ### 那么是不是线程越多,任务完成的就越快时间用的就越少呢? 答案是否定的,因为线程的执行是cpu分配的,当cpu时间分片分配到执行线程,从上个线程切换到另外一个线程这种上下文切换及启动线程是要花费时间的,这样资源都浪费到上下文切换 上面了,所以并不是线程越多就越好,得根据具体情况来 ### 线程的实现方式 线程有两种一种是继承Thread类

《Python标准库》 目录

末鹿安然 提交于 2020-03-25 05:46:41
目录 译者序 序 前言 第1章 文本 1.1 string—文本常量和模板 1.1.1 函数 1.1.2 模板 1.1.3 高级模板 1.2 textwrap—格式化文本段落 1.2.1 示例数据 1.2.2 填充段落 1.2.3 去除现有缩进 1.2.4 结合dedent和fill 1.2.5 悬挂缩进 1.3 re—正则表达式 1.3.1 查找文本中的模式 1.3.2 编译表达式 1.3.3 多重匹配 1.3.4 模式语法 1.3.5 限制搜索 1.3.6 用组解析匹配 1.3.7 搜索选项 1.3.8 前向或后向 1.3.9 自引用表达式 1.3.10 用模式修改字符串 1.3.11 利用模式拆分 1.4 difflib—比较序列 1.4.1 比较文本体 1.4.2 无用数据 1.4.3 比较任意类型 第2章 数据结构 2.1 collections—容器数据类型 2.1.1 Counter 2.1.2 defaultdict 2.1.3 deque 2.1.4 namedtuple 2.1.5 OrderedDict 2.2 array—固定类型数据序列 2.2.1 初始化 2.2.2 处理数组 2.2.3 数组与文件 2.2.4 候选字节顺序 2.3 heapq—堆排序算法 2.3.1 示例数据 2.3.2 创建堆 2.3.3 访问堆的内容 2.3.4 堆的数据极值 2

线程数,射多少更舒适?

心已入冬 提交于 2020-03-25 02:49:25
3 月,跳不动了?>>> 我相信大家都用过线程池,但是线程池数量设置为多少比较合理呢? 线程数的设置的最主要的目的是为了充分并合理地使用 CPU 和内存等资源,从而最大限度地提高程序的性能,因此让我们一起去探索吧! 首先要考虑到 CPU 核心数,那么在 Java 中如何获取核心线程数? 可以使用 Runtime.getRuntime().availableProcessor() 方法来获取(可能不准确,作为参考) 在确认了核心数后,再去判断是 CPU 密集型任务还是 IO 密集型任务: CPU 密集型任务:比如像加解密,压缩、计算等一系列需要大量耗费 CPU 资源的任务, 大部分场景下都是纯 CPU 计算 。 IO 密集型任务:比如像 MySQL 数据库、文件的读写、网络通信等任务,这类任务 不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多时间 。 在知道如何判断任务的类别后,让我们分两个场景进行讨论: CPU 密集型任务 对于 CPU 密集型计算,多线程本质上是提升多核 CPU 的利用率,所以对于一个 8 核的 CPU,每个核一个线程,理论上创建 8 个线程就可以了。 如果设置过多的线程数,实际上并不会起到很好的效果。此时假设我们设置的线程数量是 CPU 核心数的 2 倍,因为计算任务非常重,会占用大量的 CPU 资源,所以这时 CPU

关于Redis的性能瓶颈

左心房为你撑大大i 提交于 2020-03-25 02:11:06
1.首先Redis为什么这么快? 1.基于内存,不会受到硬盘IO速度的限制; 2.单线程,避免了多线程切换导致的CPU消耗,也不用考虑锁的问题,不存在加锁释放锁的操作,也不存在因死锁而导致的性能消耗; 3.使用多路I/O复用模型,非阻塞IO 多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时, 就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。 这里的多路指的是多个请求,复用指的是复用同一个线程,采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗), 且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。 2.Redis为什么是单线程? 因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦)。 也就是说,因为单线程实现及维护的成本低

如何排查用户态CPU使用率高

送分小仙女□ 提交于 2020-03-24 23:53:37
查看CPU使用 在 Linux 系统下,使用 top 命令查看 CPU 使用情况。 %Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.6 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st us(user):表示 CPU 在用户态运行的时间百分比,通常用户态 CPU 高表示有应用程序比较繁忙。典型的用户态程序有:数据库、Web 服务器等。 sy(sys):表示 CPU 在内核态运行的时间百分比(不包括中断),通常内核态 CPU 越低越好,否则表示系统存在某些瓶颈。 ni(nice):表示用 nice 修正进程优先级的用户态进程执行的 CPU 时间。nice 是一个进程优先级的修正值,如果进程通过它修改了优先级,则会单独统计 CPU 开销。 id(idle):表示 CPU 处于空闲态的时间占比,此时,CPU 会执行一个特定的虚拟进程,名为 System Idle Process。 wa(iowait):表示 CPU 在等待 I/O 操作完成所花费的时间,通常该指标越低越好,否则表示 I/O 存在瓶颈,可以用 iostat 等命令做进一步分析。 hi(hardirq):表示 CPU 处理硬中断所花费的时间。硬中断是由外设硬件(如键盘控制器、硬件传感器等)发出的,需要有中断控制器参与,特点是快速执行。 si(softirq):表示 CPU

AQS的数据结构及实现原理

可紊 提交于 2020-03-24 23:43:42
  接下来从实现角度来分析同步器是如何完成线程同步的。主要包括:同步队列、独占式同步状态获取与释放、共享式同步状态获取与释放以及超时获取同步状态等。 1、同步队列   同步器依赖内部的一个同步队列来完成同步状态的管理。当线程获取同步状态失败时,会被加入到队列中,并同时阻塞线程。当同步状态释放时,会把首节点中的线程唤醒,使其在册尝试获取同步状态。(疑问: 1、确定只唤醒首节点么,这不就是公平方式获取了么?2、首节点是否能一定获取到锁,为什么? )   a、确定只唤醒了首节点,的确这个获取方式相对比较公平,虽然新节点也可能优先获取到锁。待稍后对比重入锁获取过程;     [对比过后]:重入锁获取逻辑,就是先判断是否有人在用锁,如果有,判断是不是当前线程,如果不是,则当前线程排队,一旦进入排队队列,其实对这个队列来说,真的就是公平锁了,不公平的地方在于后来新来的线程可能会由于首节点刚好释放而获取到锁,造成“插队”;   b、首节点不一定能获取到,因为可能有新线程正好进入,然后获取了锁;   同步队列中的数据类型为Node,其中各个属性描述如下: int waitStatus 等待状态: 1 ,在队列中等待的线程等待超时或者被中断,从队列中取消等待; -1,后继节点处于等待; -2,节点在等待队列中,当condition被signal()后,会从等待队列转到同步队列; -3

高并发和多线程(1)

廉价感情. 提交于 2020-03-24 18:17:12
进程和线程 进程:一个启动正在运行的程序称之为进程。线程:是 操作系统 能够进行运算 调度 的最小单位。它包含在进程中,是进程执行的最小单元,是一个程序的运行轨迹。 一、synchronized 底层实现原理:synchronized 底层字节码文件是通过monitor指令控制线程,同步代码块儿在获取线程的开始部位添加一个monitorrenter指令,在结束部位添加一个monitorexit指令,入下图所示(代码可以通过javap命令编译查看)。为什么最后会有monitorexit命令,是为了防止中间出现异常,而最后能给正常退出,避免造成死锁。 synchronized 是可重入的锁,可重入锁的意思就是,同一个线程进入同步代码块儿是被允许的,并且在父子类之间也是可重入的。底层原理是当线程获取该锁时,计数器加一,再次获得该锁时继续加一,释放锁时,计数器减一,当计数器值为0时,表明该锁未被任何线程所持有,其它线程可以竞争获取锁。 锁优化 在一个线程要想获取锁就需要向系统内核申请资源,在这个过程是非常消耗资源的,应该是为了避免过度的申请消耗,从而在对象做了手脚;一个java对象由对象标记,类型指针,真实数据,内存补齐四部分组成: 对象标记也称Mark Word字段,存储当前对象的一些运行时数据。 类型指针,JVM根据该指针确定该对象是哪个类的实例化对象。 真实数据自然是对象的属性值。

python学习笔记(python简史)

血红的双手。 提交于 2020-03-24 17:35:55
一、python介绍 python的创始人为吉多·范罗苏姆(Guido van Rossum) 目前python主要应用领域: ·云计算 ·WEB开发 ·科学运算、人工智能 ·系统运维 ·金融:量化交易,金融分析等,作为动态语言的python,语言结构清晰简单,库丰富,成熟稳定,科学计算和统计分析都很牛 ·图形GUI python是一门什么样的语言? 编程语言主要从以下几个角度进行分类,编译型和解释型、静态语言和动态语言、强类型定义语言和弱类型定义语言。 编译型和解释型 编译型,如:c,c++,其实它和汇编语言是一样的:也是有一个负责翻译的程序来对我们的源代码进行转换,生成相对应的可执行代码。这个过程说得专业一点,就成为编译(Compile),而负责编译的程序自然就成为编译器(Compiler)。如果我们写的程序代码都包含在一个源文件中,那么通常编译之后就会直接生成一个可执行文件,我们就可以直接运行了。对于较复杂的项目,为了方便管理,我们通常把代码分散在各个源文件中,作为不同的模块来组织。这时编译各个文件时就会生成目标文件(Object file)而不是前面说的可执行文件。一般一个源文件的编译都会对应一个目标文件。这些目标文件里的内容基本上已经是可执行代码了,但由于只是整个项目的一部分,所以我们还不能直接运行。待所有的源文件的编译都大功告成,我们就可以最后把这些半成品的目标文件