本地线程

Linux多线程服务器端编程

泄露秘密 提交于 2019-12-17 14:03:31
目录 Linux多线程服务器端编程 线程安全的对象生命期管理 对象的销毁线程比较难 线程同步精要 借shared_ptr实现写时拷贝(copy-on-write) 多线程服务器的适用场合与常用编程模型 单线程服务器的常用编程模型 多线程服务器的常用编程模型 分布式系统中使用TCP长连接通信 C++多线程系统编程精要 高效的多线程日志 日志功能的需求 多线程异步日志 muduo网络库简介 TCP网络编程最本质的是处理三个半事件: 在一个端口上提供服务,并且要发挥多核处理器的计算能力 muduo编程示例 一种自动反射消息类型的Google Protobuf网络传输方案 短址服务 muduo库设计与实现 分布式系统工程实践 C++编译链接模型精要 Linux多线程服务器端编程 源码链接 。 muduo的编译安装 . 陈硕的编译教程 。 bazel编译文件不能有中文路径。 安装到指定目录: /usrdata/usingdata/studying-coding/server-development/server-muduo/build/release-install-cpp11/lib/libmuduo_base.a. 这本书前前后后看了三四遍,写得非常有深度,值得推荐。 编译和安装 . 线程安全的对象生命期管理 利用shared_ptr和weak_ptr避免对象析构时存在的竞争条件

并发编程之java内存模型(JMM)

蹲街弑〆低调 提交于 2019-12-17 12:05:22
多线程三大特性 原子性 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 一个很经典的例子就是银行账户转账问题: 比如从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元,往账户B加上1000元。这2个操作必须要具备原子性才能保证不出现一些意外的问题。 我们操作数据也是如此,比如i = i+1;其中就包括,读取i的值,计算i,写入i。这行代码在Java中是不具备原子性的,则多线程运行肯定会出问题,所以也需要我们使用同步和lock这些东西来确保这个特性了。 原子性其实就是保证数据一致、线程安全一部分, 可见性 当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 若两个线程在不同的cpu,那么线程1改变了i的值还没刷新到主存,线程2又使用了i,那么这个i值肯定还是之前的,线程1对变量的修改线程没看到这就是可见性问题。 有序性 程序执行的顺序按照代码的先后顺序执行。 一般来说处理器为了提高程序运行效率,可能会对输入代码进行优化,它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的。如下: int a = 10; //语句1 int r = 2; //语句2 a = a + 3; //语句3 r = a*a; //语句4 则因为重排序

Django异步任务线程池

女生的网名这么多〃 提交于 2019-12-17 06:13:29
当数据库数据量很大时(百万级),许多批量数据修改请求的响应会非常慢,一些不需要即时响应的任务可以放到后台的异步线程中完成,发起异步任务的请求就可以立即响应 选择用线程池的原因是:线程比进程更为可控。不像子进程,子线程会在所属进程结束时立即结束。线程可共享内存。 请求任务异步处理的原理 使用python manage.py runserver模式启动的Django应用只有一个进程,对于每个请求,主线程会开启一个子线程来处理请求。请求子线程向主线程申请一个新线程,然后把耗时的任务交给新线程,自身立即响应,这就是请求任务异步处理的原理。 可视化线程池 如果想要管理这批异步线程,知道他们是否在运行中,可以使用线程池(ThreadPoolExecutor)。 线程池会先启动若干数量的线程,并让这些线程都处于睡眠状态,当向线程池submit一个任务后,会唤醒线程池中的某一个睡眠线程,让它来处理这个任务,当处理完这个任务,线程又处于睡眠状态。 submit任务后会返回一个期程(future),这个对象可以查看线程池中执行此任务的线程是否仍在处理中 因此可以构建一个全局可视化线程池: from concurrent.futures.thread import ThreadPoolExecutor class ThreadPool(object): def init (self): # 线程池

Java深入剖析之JVM

可紊 提交于 2019-12-17 05:56:05
Java运行时数据区: Java虚拟机在执行Java程序的过程中会将其管理的内存划分为若干个不同的数据区域,这些区域有各自的用途、创建和销毁的时间,有些区域随虚拟机进程的启动而存在,有些区域则是依赖用户线程的启动和结束来建立和销毁。Java虚拟机所管理的内存包括以下几个运行时数据区域,如图: 1、程序计数器:指向当前线程正在执行的字节码指令。线程私有的。 2、虚拟机栈:虚拟机栈是Java执行方法的内存模型。每个方法被执行的时候,都会创建一个栈帧,把栈帧压人栈,当方法正常返回或者抛出未捕获的异常时,栈帧就会出栈。 (1)栈帧:栈帧存储方法的相关信息,包含局部变量数表、返回值、操作数栈、动态链接 a、局部变量表:包含了方法执行过程中的所有变量。局部变量数组所需要的空间在编译期间完成分配,在方法运行期间不会改变局部变量数组的大小。 b、返回值:如果有返回值的话,压入调用者栈帧中的操作数栈中,并且把PC的值指向 方法调用指令 后面的一条指令地址。 c、操作数栈:操作变量的内存模型。操作数栈的最大深度在编译的时候已经确定(写入方法区code属性的max_stacks项中)。操作数栈的的元素可以是任意Java类型,包括long和double,32位数据占用栈空间为1,64位数据占用2。方法刚开始执行的时候,栈是空的,当方法执行过程中,各种字节码指令往栈中存取数据。 d、动态链接

VisualVM分析与HelloWorld、springBoot项目

不问归期 提交于 2019-12-17 04:13:26
VisualVM分析与HelloWorld、springBoot项目 自从1995年第一个JDK版本JDKBeta发布,至今已经快25年,这些年来Java的框架日新月异,从最开始的Servlet阶段,到SSH,SSI,SSM,springboot等,还有一些其他方向的框架微服务SpringCloud、响应式编程Spring Reactor。零零总总 的框架,我们都需要去熟悉,那么怎么去快速熟悉呢,我觉得可以看源码,可以看博客,也可以根据内存分配去完善理解。 那么问题来了,一个Java项目在咱们平时启动项目的时候,究竟发生了什么,创建几个简单的项目,用VisualVM来分析一下~ Main 简单的项目,应该没有比HelloWorld更简单的了吧,按照老规矩,咱们就从HelloWorld开始分析!那么简单的项目大家都能闭着眼睛敲出来,是不是没分析的必要啊,别着急,写好HelloWorld咱们开始分析: System.out.println("HelloWorld start"); // 这里让线程睡一会,方便分析 Thread.sleep(100000); System.out.println("HelloWorld end"); 运行main方法,打开VisualVM,发现事情并不简单哦,这个简单的项目有十六个线程维护,其中守护线程有十五个。 其中几大线程的内存分配情况如下:

Django异步任务线程池

荒凉一梦 提交于 2019-12-16 19:56:30
当数据库数据量很大时(百万级),许多批量数据修改请求的响应会非常慢,一些不需要即时响应的任务可以放到后台的异步线程中完成,发起异步任务的请求就可以立即响应 选择用线程池的原因是:线程比进程更为可控。不像子进程,子线程会在所属进程结束时立即结束。线程可共享内存。 请求任务异步处理的原理 使用 python manage.py runserver 模式启动的Django应用只有一个进程,对于每个请求,主线程会开启一个子线程来处理请求。请求子线程向主线程申请一个新线程,然后把耗时的任务交给新线程,自身立即响应,这就是请求任务异步处理的原理。 可视化线程池 如果想要管理这批异步线程,知道他们是否在运行中,可以使用线程池(ThreadPoolExecutor)。 线程池会先启动若干数量的线程,并让这些线程都处于睡眠状态,当向线程池submit一个任务后,会唤醒线程池中的某一个睡眠线程,让它来处理这个任务,当处理完这个任务,线程又处于睡眠状态。 submit任务后会返回一个期程(future),这个对象可以查看线程池中执行此任务的线程是否仍在处理中 因此可以构建一个全局可视化线程池: from concurrent.futures.thread import ThreadPoolExecutor class ThreadPool(object): def __init__(self): #

Java并发编程:深入剖析ThreadLocal

断了今生、忘了曾经 提交于 2019-12-16 15:59:53
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。   以下是本文目录大纲:   一.对ThreadLocal的理解   二.深入解析ThreadLocal类   三.ThreadLocal的应用场景   若有不正之处请多多谅解,并欢迎批评指正。   请尊重作者劳动成果,转载请标明原文链接:    http://www.cnblogs.com/dolphin0520/p/3920407.html 一.对ThreadLocal的理解 ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,其实意思差不多。可能很多朋友都知道ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。   这句话从字面上看起来很容易理解,但是真正理解并不是那么容易。   我们还是先来看一个例子: class ConnectionManager { private static Connection connect = null; public static

java面试题

混江龙づ霸主 提交于 2019-12-16 13:12:43
1、多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法: 1)发挥多核CPU的优势 随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。 2)防止阻塞 从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题

JVM内存结构概述

大兔子大兔子 提交于 2019-12-16 07:04:19
写在前面 基本问题: 介绍下 Java 内存区域(运行时数据区)。 JDK7 和 JDK8 在内存结构上有什么变化 拓展问题: String 类和常量池 8种基本类型的包装类和常量池 概述 由于 java 语言天生自带内存自动管理机制,所以 java 程序开发时几乎不用考虑内存的回收,不再需要像 C/C 程序开发那样为一个 new 出来的对象去写对应的 delete/free 操作,也不容易出现内存泄露和内存溢出问题。也正是因为 java 程序将内存管理都交给 JVM 来处理,如果不了解虚拟机是怎样使用内存的,那么排查错误将会是一个非常艰巨的任务。 运行时数据区域 根据 Java 虚拟机规范 的规定, Java 虚拟机(Java Virtual Machine, JVM)在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域:程序计数器(Program Counter Register)、Java虚拟机栈(JVM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s5k0RGeU-1576162066977)(https://xiaolong.li/images/jvm/2019-10-07-jvm-jdk-6.jpg

Java内存区域

旧巷老猫 提交于 2019-12-16 02:25:40
根据Java虚拟机规范,Java虚拟机会把Java的所管理的内存分成几个区域,分别为:程序计数器,Java虚拟机栈,本地方法栈,堆,方法区 通过一张图来了解一下: 先要说明的一点是,java虚拟机栈,本地方法栈和程序计数器是线程私有的,方法区,堆是线程共享的,接下来逐一介绍 程序计数器 程序计数器是一块较小的内存空间 可以把程序计数器理解为方法执行的行号指标,字节码解释器可以通过改变这个计数器的值来选取下一条需要执行的字节码指令。实现分支,循环,跳转,异常处理,线程恢复等基础功能都需要依赖这个计数器来完成。 程序计数器是线程私有的,为什么是线程私有的?即使Java中的多线程,高并发,他们只是在宏观上实现并发,但不是并行。所以多个线程时通过切换来分配cpu的时间片,任何一个时刻,一个处理器都只会执行一条线程中的指令,需要程序计数器来保证切换后线程能恢复到正确的执行位置,这样就能理解程序计数器为什么是线程私有的。 如果线程执行的是普通方法,那么程序计数器记录的是正在执行的虚拟机字节码指令的地址;如果线程执行的是native方法,那么程序计数器为空。 该区域没有规定任何OutOfMemoryError 虚拟机栈 虚拟机栈也是线程私有的 虚拟机栈描述的是Java方法的内存模型,每个方法在执行的同时都会创建一个 栈帧 ,在栈帧中有局部变量表,操作数栈,动态链接,方法接口等信息