java线程和go协程
一、线程的实现
线程的实现方式主要有三种:内核线程实现、用户线程实现、用户线程加轻量级进程混合实现。因为自己只对java的线程比较熟悉一点,所以主要针对java线程和go的协程之间进行一个对比。
线程模型主要有三种:1、内核级别线程;2、用户级别线程;3、混合线程
1、内核级别线程
内核级别线程就是直接由操作系统的内核(kernel)支持的线程,这种方式实现的线程主要通过内核的调度器来进行调度,由内核完成线程切换。一般来讲程序不会直接调用系统内核线程,而是利用内核线程的一种高级接口-轻量级进程(Light Weight Process,即LWP,它也可以视为用户线程),也就是我们平时所说的线程,每一个LWP都是由一个内核线程支持,也就是先有内核线程,再有LWP。这种LWP与内核线程之间1:1的关系称为一对一线程模型,这是一种最简单的线程实现方式。见下图:
2018-11-16 22-40-01 的屏幕截图.png
这种方式创建的每一个线程都需要由一个内核线程支持,需要消耗一定的内核资源,因此一个系统支持的线程数量是有限的。另外由于基于内核线程实现,这种方式创建的线程操作需要进行系统调用,而系统调用代价较高,需要在用户态和内核态进行切换(这个我也不懂)。
2、用户级别线程
这里所指的用户级线程主要是创建在用户空间的线程库上,系统内核感受不到线程的实现方式。用户线程的建立、同步、销毁等在用户态中完成,不需要内核的介入。这种进程和用户线程(UT)之间1:N的关系称为一对多线程模型。
1321313.jpg
这种方式的优势就是上下文切换比较快,缺点是无法从多线程处理器或多处理器计算机上的硬件加速中受益,同时调度的线程永远不会超过一个。
3、混合线程
这种方式相当于是第一种方式和第二种方式的混合,即有LWT,也有用户线程,这种方式中用户线程(UT)和LWT的数量比是不定的,即所谓的N:M关系,也就是所谓的多对多模型。这种实现线程的方式相比前两种也更为复杂,这种方式中由线程库负责在可用的可调度实体上调度用户线程,这使得线程的上下文切换非常快,因为它避免了系统调用。但是增加了复杂性和优先级倒置的可能性,以及在用户态调度程序和内核调度程序之间没有广泛(且高昂)协调的次优调度。
3213213123.jpg
java线程实现
主要说下常用的hotspot的JVM,采用的是第一种1:1的线程模型,即:map a java thread to a native thread,也就是说java线程会和native线程有个一一映射的关系,如果看下java的Thread类就可以发现有很多的native方法,这就涉及到操作系统的线程了。
二、go语言并发模式
go语言支持两种并发模式,一种是Communicating Sequential Processes(CSP)模式,这种模式中值是在相互独立的协程(goroutine)中传递的,协程和协程之间使用到就是上次说到的channel。另外一种就是我们比较传统的模式,也是我们相对熟悉的模式Share Memory Multithreading。但是go语言推荐的还是第一种模式,go官网文档是说:Do not communicate by sharing memory; instead, share memory by communicating.也就是说不建议线程或协程之间通过共享内存通讯,而是通过通讯共享内存。比方说比较熟悉的java其实就是共享内存模式的并发模式,在涉及到多线程的问题时,必须考虑共享数据的安全性。
三、线程和协程之间的区别
这里说的协程指的只是go语言的goroutine。线程和协程的区别主要是数量上的,而不是性质上,所以说协程从逻辑上来说也是线程。
栈的大小:
1、线程栈
操作系统的线程一般都分配有一块固定大小的内存块(一般来说大小是2M,这个需要查证),我查找资料显示的64位Linux上,hotspot虚拟机的栈的大小默认为1M,地址:https://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html。。栈存储的是方法的局部变量或者一些基本数据类型(java中)。因为栈的大小是固定的,在执行某些方法的时候可能就不太够用,比如一些比较复杂或则一些深的递归操作,比如熟悉的java有时候会有栈溢出异常;当然某些时候2M可能显得有点大,这样从一定程度上来说又造成了浪费。
2、协程
协程开始的时候也会分配一定大小的内存区域,一般只有2K,和线程的栈一样,协程的栈存储的也是局部变量,但是不同的是协程的栈的大小是不固定的,是可以根据需要自动调整大小的,最大甚至可以达到1G,所以灵活性非常好。
调度方式
1、系统级别的线程是由操作系统的内核(kernel)调度的,每过几毫秒,硬件的计时器就会中断处理器,从而引起被成为调度器的内核函数执行。调度器会暂停当前正在执行的线程,并把它的寄存器存到内存中,并查看线程列表决定接下来执行哪一个线程,然后从内存中恢复改线程的寄存器,最后恢复该线程的执行。因为线程是通过内核调度的,从一个线程切换到另一个线程就涉及到上下文转换,建议看下维基百科:https://en.wikipedia.org/wiki/Context_switch。简单说就是将一个用户线程的状态保存到内存,恢复另一个用户线程的状态,并且更新调度程序的数据结构,导致上下文切换比较慢。
2、go语言使用了所谓的N:M调度的技术实现了自己的调度器,它在N个系统线程上多路复用(或调度)M个协程,也就是说由n个系统线程,生成了m个go的协程(可以这么理解吧?)。go语言的调度工作类似于系统内核的调度,但是它只关注单个go程序的协程。
另外一点就是go的协程是没有标识的,在java中当前执行的线程都会有一个唯一的标识,它的好处就是可以很容易的就构建出一个抽像的"thread-local storage",即java中的ThreadLocal,每个线程都可以创建出这样一个数据结构存储只属于当前线程的一些变量。但是goroutine并不支持,因为ThreadLocal可能会被滥用。go语言提倡的是一种更简单的编程方式,即参数影响函数的行为应该是显性的。
go因为在创建协程的数量上一般没有特别的限制,所以可以很轻松的创建出很多个协程出来,而java因为采用的是1:1的线程模型,线程数量特别是并发线程数会受到CPU和操作系统的限制(我记得java线程池会获取当前可使用的CPU核数,可能有误),所以并发性能上应该不如go语言,有人也说go语言天生就带有高并发光环加持。这里无意区分java和go孰优孰劣,只是想从线程和协程的实现上来简单的了解下二者的差别。
作者:非典型_程序员
链接:https://www.jianshu.com/p/6168b10dee34
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
java线程和go协程 - 简书
相关文章:

java线程和go协程
一、线程的实现 线程的实现方式主要有三种:内核线程实现、用户线程实现、用户线程加轻量级进程混合实现。因为自己只对java的线程比较熟悉一点,所以主要针对java线程和go的协程之间进行一个对比。 线程模型主要有三种:1、内核级别线程&#…...
JAVA 时间戳
时间戳(Timestamp)是一个表示特定时间点的数值,通常指的是自某个固定的起始时间(如1970年1月1日00:00:00 UTC)以来经过的秒数或毫秒数。 在 Java 中,可以使用 System.currentTimeMillis() 方法获取当前的时…...

层次分析法(matlab实现)
1.层次分析法(AHP) 在决策理论中,层次分析法是一种以数学和心理学为基础,组织和分析复杂决策的结构化技术,它代表了一种量化决策标准权重的准确方法,通过成对比较,利用个别专家的经验来估计因素…...
python selenium 自动化登录页面
去掉自动化标识,绕过js,绕过ip import time from selenium import webdriver from selenium.webdriver.chrome.options import Options# 去掉自动化标识,绕过js option Options() option.add_experimental_option(excludeSwitches, [enable…...

【Linux】高级IO --- 多路转接,select,poll,epoll
所有通过捷径所获取的快乐,无论是金钱、性还是名望,最终都会给自己带来痛苦 文章目录 一、五种IO模型1.什么是高效的IO?(降低等待的时间比重)2.有哪些IO模型?哪些模型是高效的?3.五种IO模型的特…...

anaconda navigator打不开,一直在loading画面
anaconda navigator打不开,一直在loading画面。百度解决方法,用网上的方法在命令窗口里运行conda update anaconda结果一直显示 solving environment卡在那里。又尝试用管理员身份运行还是不行,打开后出现There in aninstance of Anaconda Na…...

【Java基础】深入理解反射、反射的应用(工厂模式、代理模式)
文章目录 1. Java反射机制是什么?1.2 Java反射例子 2. Java反射机制中获取Class的三种方式及区别?3. Java反射机制的应用场景有哪些?3.1. 优化静态工厂模式(解耦)3.1.1 优化前(工厂类和产品类耦合ÿ…...
VUE 项目 nginx部署
server {listen 80; # 监听的端口号server_name 129.204.189.149; # 服务器的ip或者域名#charset koi8-r;#access_log logs/host.access.log main;# 前端服务反向代理配置location / {proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header X-Real-…...

Hashtable和HashMap、ConcurrentHashMap 之间的区别
Hashtable和HashMap的区别 HashMap和Hashtable都是哈希表数据结构,但是Hashtable是线程安全的,HashMap是线程不安全的 Hashtable实现线程安全就是简单的把关键方法都加上了synchronized关键字 直接在方法上添加synchronized相当于针对this对象࿰…...

包管理工具--》npm的配置及使用(二)
在阅读本篇文章前请先阅读包管理工具--》npm的配置及使用(一) 目录 🌟语义版本 避免还原的差异 npm的差异版本处理 🌟npm 脚本 (npm scripts) 🌟运行环境配置 在node中读取package.json …...

【Linux】多线程2——线程互斥与同步/多线程应用
文章目录 1. 线程互斥1.1 问题引入1.2 线程互斥的相关概念1.3 互斥量mutex1.4 互斥量实现原理1.5 死锁 2. 线程安全和可重入函数3. 线程同步3.1 同步概念3.2 条件变量 4. 生产消费模型4.1 基于阻塞队列的cp模型4.2 基于环形队列的cp模型POSIX信号量 5. 线程池5.1 互斥量RAII版本…...
Python中的函数式编程是什么?
Python中的函数式编程是一种编程范式,它强调使用纯函数和避免可变状态来构建程序。函数式编程的核心思想是将计算视为函数的求值,而不是通过改变状态来实现。在函数式编程中,函数被视为一等公民,可以作为参数传递给其他函数&#…...

8月《中国数据库行业分析报告》已发布,聚焦数据仓库、首发【全球数据仓库产业图谱】
为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况,从2022年4月起,墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》,持续传播数据技术知识、努力促进技术创新与行业生…...

TikTok Shop|如何成为定邀卖家?
TikTok在商品售卖资质和商家资质上做了很多限制,比如我们熟知的珠宝类目,今天我们结合TikTok Shop规则中心8月30号发布的《如何申请成为“定邀”卖家》和关于“定邀”商品的政策进行分析,看看如何成为“定邀”卖家。 定邀商品/类目有哪些&am…...
C++二级题目6
数字放大 #include<iostream> #include<string.h> #include<stdio.h> #include<iomanip> #include<cmath> #include<bits/stdc.h> int a[2000][2000]; int b[2000]; char c[2000]; long long n; using namespace std; int main() {int x;…...

南方科技大学博士研究生奖助学金,深圳大学
目录 南方科技大学 中南大学 南京大学 厦门大学 苏州大学 中南财经政法大学 深圳大学 南方科技大学 https://ocean.sustech.edu.cn/ocean/public/upload/download/3/2.pdf 南方科技大学的在读研究生,每人每年都会得到40000元的补助,这40000块钱分…...

QT 使用信号与槽实现界面跳转
一、创建一个新的页面 1 > 在原有工程上新建一个页面 2 > 选择Qt - Qt 设计师界面类 - choose 3 > 选择Widget模板 - 下一步 4 > 输入自定义类名 - 下一步 会自动生成其同名的.h .cpp .ui文件 5 > 最终效果 Headers存放.h文件 Soueces存放.cpp文件 Forms存放.u…...

Burp插件HaE与Authz用法
HaE与Authz均为BurpSuite插件生态的一员,两者搭配可以避免“越权”、“未授权”两类漏洞的重复测试行为。(适用于业务繁杂,系统模块功能多的场景) 两个插件都可以在store里安装 安装完后,点击Filter Settings勾选Sho…...

element+vue table表格全部数据和已选数据联动
1.组件TableChoose <template><div class"tableChooseBox"><div class"tableRow"><div class"tableCard"><div class"tableHeadTip">全部{{ labelTitle }}</div><slot name"body" …...
vue 防抖与节流用法
一、html <template><button click"getData">获取数据</button> </template>二、JS import { throttle } from "/utils/common"; export default {methods:{getData: throttle(async function(params){console.log(”获取接口数…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...