高速缓存

Java多线程之synchronized和volatile

爱⌒轻易说出口 提交于 2020-01-05 03:40:18
概述 用Java来开发多线程程序变得越来越常见,虽然Java提供了并发包来简化多线程程序的编写,但是我们有必要深入研究一下,才能更好的掌握这块知识。 本文主要对Java提供的底层原语synchronized和volatile进行分析,看看他们究竟干了什么,以及怎么样才能合理的使用它们。 运算速度与IO速度的问题 现代计算机模型,待计算的数据主要存储在内存中,CPU想要对数据进行计算,就必须要经过下面的流程:从内存读取数据-->CPU计算-->把计算结果写回内存。但是,不得不承认一个事实,就是CPU与内存之间的IO速度,要比CPU的运算速度慢很多,所以这样就不能充分发挥CPU的计算能力。 为了解决这个问题,引入了高速缓存的概念,它一般位于内存与CPU之间,与CPU之间有较高的IO速度。高速缓存存放常用的数据,这样就可以大幅度提高CPU的利用率。 由缓存命中问题引出的指令重排序 上面提到了高速缓存之间的概念。既然提到高速缓存,那么就要谈到缓存命中的问题,如果缓存命中率很高,那么整体性能就会提升。所以,试想一下,有下面几行代码: int a = 0; a = a + 10; int b = 0; b = b + 5; a = a * 2; 通常我们会认为,执行完第2条代码后,a被写入到高速缓存,然后执行对b的操作,最后再从高速缓存中读取出a,再对a做乘法计算。 但是

Java多线程编程(3)--线程安全性

核能气质少年 提交于 2020-01-05 03:31:10
一.线程安全性   一般而言,如果一个类在单线程环境下能够运作正常,并且在多线程环境下,在其使用方不必为其做任何改变的情况下也能运作正常,那么我们就称其是线程安全的。反之,如果一个类在单线程环境下运作正常而在多线程环境下则无法正常运作,那么这个类就是非线程安全的。因此, 一个类如果能够导致竞态,那么它就是非线程安全的;而一个类如果是线程安全的,那么它就不会导致竞态。下面是《Java并发编程实战》一书中给出的对于线程安全的定义: 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。   使用一个类的时候我们必须先弄清楚这个类是否是线程安全的。因为这关系到我们如何正确使用这些类。Java标准库中的一些类如ArrayList、HashMap和SimpleDateFormat,都是非线程安全的,在多线程环境下直接使用它们可能导致一些非预期的结果,甚至是一些灾难性的结果。一般来说,Java标准库中的类在其API文档中会说明其是否是线程安全的(没有说明其是否是线程安全的,则可能是也可能不是线程安全的)。   从线程安全的定义上我们不难看出,如果一个线程安全的类在多线程环境下能够正常运作,那么它在单线程环境下也能正常运作。既然如此

分配内存时如何减少内存碎片

那年仲夏 提交于 2019-12-25 13:16:48
  感觉面试的时候经常会被问到这个问题,然后我也学习了一下Memcached的slab机制,发现很多服务器都是使用这种机制来分配内存,所以决定学习一下。   首先,先对内存分配中的伙伴系统有初步的了解:   在编程和使用的服务器软件中,经常需要分配一组连续的页框,而频繁地申请和释放不同大小的连续页框,必然导致在已分配页框的内存块中分散了许多小块的空闲页框。这样,即使这些页框是空闲的,但要分配一个大块的连续页框就可能无法满足。   而Linux采用了伙伴系统来解决上述难题。把所有的空闲页框分组为11个块链表,每个块链表分别包含大小为1,2,4,8,16,32,64,128,256,512和1024个连续页框的页框块。最大可以申请1024个连续页框,对应4MB大小的连续内存。每个页框块的第一个页框的物理地址是该块大小的整数倍。例如,大小为16个页框的块,其起始地址是16×212的倍数。 假设要申请一个256个页框的块,先从256个页框的链表中查找空闲块,如果没有,就去512个页框的链表中找,找到了则将页框块分为2个256个页框的块,一个分配给应用,另外一个移到256个页框的链表中。如果512个页框的链表中仍没有空闲块,继续向1024个页框的链表查找,如果仍然没有,则返回错误。 页框块在释放时,内核会主动将两个互为伙伴的页框块合并为一个较大的页框块

(十)Linux 网络编程之ioctl函数

旧街凉风 提交于 2019-12-25 03:12:26
1.介绍 Linux网络程序与内核交互的方法是通过ioctl来实现的,ioctl与网络协议栈进行交互,可得到网络接口的信息,网卡设备的映射属性和配置网络接口.并且还能够查看,修改,删除ARP高速缓存的信息,所以,我们有必要了解一下ioctl函数的具体实现. 2.相关结构体与相关函数 #include int ioctl(int d,int request,....); 参数: d-文件描述符,这里是对网络套接字操作,显然是套接字描述符 request-请求码 省略的部分对应不同的内存缓冲区,而具体的内存缓冲区是由请求码request来决定的,下面看一下具体都有哪些相关缓冲区。 (1)网络接口请求结构ifreq struct ifreq{ #define IFHWADDRLEN 6 //6个字节的硬件地址,即MAC union{ char ifrn_name[IFNAMESIZ];//网络接口名称 }ifr_ifrn; union{ struct sockaddr ifru_addr;//本地IP地址 struct sockaddr ifru_dstaddr;//目标IP地址 struct sockaddr ifru_broadaddr;//广播IP地址 struct sockaddr ifru_netmask;//本地子网掩码地址 struct sockaddr ifru

计算机基础系列一:计算机硬件

 ̄綄美尐妖づ 提交于 2019-12-21 04:41:30
一 为何要学习计算机基础 python是编程语言,即python是语言 语言有英语、法语、葡萄牙语等,但凡是语言,都是用来沟通的介质。 程序员编程的本质就是让计算机去工作,而编程语言就是程序员与计算机沟通的介质 程序员要想让计算机工作,必须知道计算机能干什么,怎么干的,这也就是我们必须学习计算机基础的原因 然而光有编程语言和硬件也并不能满足大家的编程需求,为什么这么说呢? 程序用编程语言写程序,最终开发出的结果就是一个软件,既然是软件,那就与腾讯qq、暴风影音、快播等软件没有区别了。这些软件必须运行在操作系统之上,你肯定会问:为何要有操作系统呢?没错,远古时代的程序员确实是在没有操作系统的环境下,用编程语言之间操作硬件来编程的,你可能觉得这没有问题,但其实问题是相当严重的,因为此时你必须掌握如何操作硬件的所有具体细节,比如如何具体操作硬盘(现在你得把硬盘拆开,然后你能看见的所有的东西,你都得研究明白,因为你编程时要用到它),这就严重影响了开发的效率,操作系统的出现就是运行于硬件之上,来控制硬件的,我们开发时,只需要调用操作系统为我们提供的简单而优雅的接口就可以了 所以一套完整的计算机系统分为:计算机硬件,操作系统,应用软件,如下图。因而我们的python编程之路分为计算机硬件基础,操作系统基础,和python编程三部分,就让我们先从计算机硬件学起吧 二 本节目标

linux free 命令

安稳与你 提交于 2019-12-18 16:04:30
free 命令显示系统内存的使用情况,包括物理内存、交换内存(swap)和内核缓冲区内存。 如果加上 -h 选项,输出的结果会友好很多: 有时我们需要持续的观察内存的状况,此时可以使用 -s 选项并指定间隔的秒数: $ free -h -s 3 上面的命令每隔 3 秒输出一次内存的使用情况,直到你按下 ctrl + c。 (Ubuntu 16.04 中默认的 free 版本有 bug,使用 -s 选项时报错,所以这张图是在 CentOS 中截的。) 由于 free 命令本身比较简单,所以本文的重点会放在如何通过 free 命令了解系统当前的内存使用状况。 输出简介 下面先解释一下输出的内容: Mem 行(第二行)是内存的使用情况。 Swap 行(第三行)是交换空间的使用情况。 total 列显示系统总的可用物理内存和交换空间大小。 used 列显示已经被使用的物理内存和交换空间。 free 列显示还有多少物理内存和交换空间可用使用。 shared 列显示被共享使用的物理内存大小。 buff/cache 列显示被 buffer 和 cache 使用的物理内存大小。 available 列显示还可以被应用程序使用的物理内存大小。 我想只有在理解了一些基本概念之后,上面的输出才能帮助我们了解系统的内存状况。 buff/cache 先来提一个问题: buffer 和 cache

Linux内存管理中的slab分配器

折月煮酒 提交于 2019-12-17 08:28:58
转载自: http://edsionte.com/techblog/archives/4019 Linux内核中基于伙伴算法实现的分区页框分配器适合大块内存的请求,它所分配的内存区是以页框为基本单位的。对于内核中小块连续内存的请求,比 如说几个字节或者几百个字节,如果依然分配一个页框来来满足该请求,那么这很明显就是一种浪费,即产生内部碎片(internal fragmentation) 为了解决小块内存的分配,Linux内核基于Solaris 2.4中的slab分配算法实现了自己的slab分配器。除此之外,slab分配器另一个主要功能是作为一个高速缓存,它用来存储内核中那些经常分配并释放的对象。 1.slab分配器的基本原理 slab分配器中用到了对象这个概念,所谓对象就是内核中的数据结构以及对该数据结构进行创建和撤销的操作。它的基本思想是将内核中经常使用的对象 放到高速缓存中,并且由系统保持为初始的可利用状态。比如进程描述符,内核中会频繁对此数据进行申请和释放。当一个新进程创建时,内核会直接从slab分 配器的高速缓存中获取一个已经初始化了的对象;当进程结束时,该结构所占的页框并不被释放,而是重新返回slab分配器中。如果没有基于对象的slab分 配器,内核将花费更多的时间去分配、初始化以及释放一个对象。 slab分配器有以下三个基本目标: 1

Linux服务之高速缓存DNS

霸气de小男生 提交于 2019-12-10 16:19:34
DNS总览 1 . 权威名称服务器 存储并提供某区域(整个DNS域或DNS域的一部分)的实际数据。 2 . 权威名称服务器的类型包括: Master :包含原始区域数据,有时称作主要名称服务器; Slave :备份服务器,通过区域传送从Master服务器获得区域数据的副本,有时称作次要名称服务器。 3 . 非权威/递归名称服务器 客户端通过其查找来自权威名称服务器的数据。 递归名称服务器的类型包括仅缓存名称服务器:仅用于查找,对于非重要数据之外的任何内容都不具有权威性。 什么是域名解析 域名解析是为了方便记忆,DNS服务器将容易记住的域名解析成ip,当人们访问web站点时,不需要记住ip地址,只需要输入域名就可以直接访问到。 域名解析过程 在internet上的计算机是通过ip地址来定位的,给出一个ip地址,就可以找到与之对应的主机,但是ip数串是难记的,就发明了域名来代替ip地址,但是通过域名并不能访问到主机,中间添加一个依据域名来查找ip地址的过程,这个过程就是域名解析。 高速缓存DNS DNS服务器可以高速缓存从其他DNS服务器收到DNS记录,也可以在DNS客户服务器中使用高速缓存,将其作为DNS 客户端保存在最近的查询过程中得到的信息高速缓存的方法。 高速缓存DNS的作用 当一个主机第一次访问一个网页时,该主机的DNS服务器从远处的服务器拿到数据(address

Java基础之Volatile原理

无人久伴 提交于 2019-12-05 23:05:18
原文链接: http://www.aoaoyi.com/archives/956.html 计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据 的读取和写入。由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就 存在一个问题,由于CPU执行速度很快,而从内存读取数据和向内存写入数据的过程跟CPU 执行指令的速度比起来要慢的多,因此如果任何时候对数据的操作都要通过和内存的交互来 进行,会大大降低指令执行的速度。因此在CPU里面就有了高速缓存。当程序在运行过程 中,会将运算需要的数据从主存复制一份到CPU的高速缓存当中,那么CPU进行计算时就可 以直接从它的高速缓存读取数据和向其中写入数据,当运算结束之后,再将高速缓存中的数 据刷新到主存当中。举个简单的例子,比如下面的这段代码: i = i + 1; 当线程执行这个语句时,会先从主存当中读取 i 的值,然后复制一份到高速缓存当中, 然后 CPU 执行指令对 i 进行加1操作,然后将数据写入高速缓存,最后将高速缓存 中 i 最新的值刷新到主存当中。 这个代码在单线程中运行是没有任何问题的,但是在多线程中运行就会有问题了。在多核 CPU 中,每条线程可能运行于不同的 CPU 中,因此 每个线程运行时有自己的高速缓存(对 单核CPU来说,其实也会出现这种问题,只不过是以线程调度的形式来分别执行的

ioctl操作

拥有回忆 提交于 2019-12-05 17:52:00
  在本书中有两个地方都对这个函数进行了介绍,其实还有很多地方需要这个函数。ioclt函数传统上一直作为纳西而不适合归入其他精细定义类别的特性的系统接口。网络程序(特别是服务器程序)经常在程序启动执行后使用ioctl获取所在主机全部网络接口的信心,包括:接口地址、是否支持广播、是否支持多播。 #include <unistd.h> int ioctl(int fd,int request,...../* void *arg /); //返回:若成功则为0.失败则我-1 套接字操作 文件操作 接口操作 ARP高速缓存操作 路由表操作 流系统   不但某些ioclt操作和某些fcntl操作功能重叠(譬如把套接字设置为非阻塞),而且某些操作可以使用ioctl以不止一种方式制定(譬如设置套接字的进程组属主)。下表列出了网络相关ioctl请求的request参数以及arg地址必须指向的数据类型。 套接字操作   明确要求套接字ioctl请求有三个,它们都要求ioctl的第三个参数是指向某个整数的一个指针。 SIOCATMARK:如果本套接字的读指针当前位于带外标记,那就通过由第三个参数指向的帧数放回一个非0值,否则返回一个0值。 SIOCGPGRP:通过由第三个参数指向的整数返回本套接字的进程ID或进程组ID,该ID指定针对本套接字的SIGIO或SIGURG信号的接受进程。 SIOCSPGR