细读jsr中的yield语义,或者不是我们想象中的那样
这只是我的个人观点,如有错误,希望你可以指出。
首先英文原版

中文译版

我觉得“不需要”还会让人产生误解,应该译为不一定要。
很多时候会被断章取义地理解,我们一定要有“不一定”,“可能”的意识,下面给出一段代码演示,亲测。
static boolean close=false;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{ //且称线程1
int count=1;
while(!close){
Thread.yield(); //sleep()有同样的效果
count++;
}
System.out.println("yield"+count);//等待io
}).start();
Thread.sleep(100);
close=true;
}
//yield77616,这个数在70000-110000左右
线程是会停止的,这时候断章取义者就会百思不得其解。
那么jsr中的又是什么意思呢?
是基于这样的一个假设的:
主线程在cpu0上运行。
线程1一直在cpu1上运行,虽然线程1 yield,但是没有别的线程来使用cpu1,意思为cpu1中寄存器,缓存中存着的还是线程1的数据,如变量close。
然而,如果在线程1 yield或者sleep的时候,操作系统调度别的线程来使用cpu1,那么cpu1中存放的旧数据将会刷回主存(实际刷回时机视实际情况,不同的cpu应该会有不同的策略),然后存放别的线程所需的数据。那么等到线程1 yield或者sleep完毕,到它使用cpu1(不一定是cpu1)的时候,发现没有命中缓存,就会从主存中把变量close读取进来,而这个时候主存当中的close已经被主线程修改为true了,因此循环结束。
而实际情况是,时时刻刻都有大量的线程在工作,你放弃了就会有别人来用。
所以它真正强调的意思是“不主动”,而像volatile就会主动去做某些措施。
继续补充
static boolean close=false;
public static void main(String[] args) throws InterruptedException {
new Thread(()->{
//int count=1;
while(!close){
System.out.println("io操作");
}
System.out.println("io操作完毕");
}).start();
Thread.sleep(100);
close=true;
}
// io操作
// io操作
// .
// .
// .
// io操作
// io操作完毕
如上,线程1在进行IO操作的时候,将会有别的线程来使用cpu1,线程1照样结束循环。
只有这样才不会结束
while(!close){
}
总结
一言以蔽之,只要cpu没有命中缓存,就会从主存中读取。
再补充
可能会觉得,那这样的话,yield和sleep就像是普通的正常的操作(反正肯定会有别的线程来使用cpu)啊,有必要这样强调吗?
我觉得
一是文档的规范性,完整性。
二,也是曾在“为什么java的称为虚拟机,而python的称为解释器”这样的问题中,看到的一个答案。(不保证正确)
jvm是模仿着硬件去设计的,像一些操作,取操作码,取操作数,push,store等指令。如果按照jvm去配置硬件,有可能做到cpu中就只有jvm的线程在跑,或者说通俗点说jvm就是操作系统。那这样的话,就真的满足之前的假设了——“线程1一直在cpu1上运行,虽然线程1 yield,但是没有别的线程来使用cpu1”。
细读jsr中的yield语义,或者不是我们想象中的那样的更多相关文章
- Python3中的yield from语法
Python3中的yield from语法 by Kay Zheng Tags: python, 协程, generator 30 March 2014 2016-2-23 更新 這篇文章是兩年前寫的 ...
- 可惜Java中没有yield return
项目中一个消息推送需求,推送的用户数几百万,用户清单很简单就是一个txt文件,是由hadoop计算出来的.格式大概如下: uid caller 123456 12345678901 789101 12 ...
- 初次使用C#中的yield
这几天在Python程序员的微信订阅号中总是见到yield的关键字,才想起来在C#中也是有yield,但是只是知道有,从来没有了解过他的用法,今天有时间就来看看是怎么使用的.刚开始肯定就是搜索一下用法 ...
- C#中的yield return与Unity中的Coroutine(协程)(上)
C#中的yield return C#语法中有个特别的关键字yield, 它是干什么用的呢? 来看看专业的解释: yield 是在迭代器块中用于向枚举数对象提供值或发出迭代结束信号.它的形式为下列之一 ...
- 关于Python中的yield
关于Python中的yield 在介绍yield前有必要先说明下Python中的迭代器(iterator)和生成器(constructor). 一.迭代器(iterator) 在Python中,f ...
- 关于Python中的yield(转载)
您可能听说过,带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ? 我们先抛开 generator,以一个常见的编程题目来展示 yield ...
- C#中的yield return用法演示源码
下边代码段是关于C#中的yield return用法演示的代码. using System;using System.Collections;using System.Collections.Gene ...
- python 中的 yield 究竟为何物?生成器和迭代器的区别?
当你突然看到别人的代码中出现了一个好像见过但又没用过的关键词 比如 yield ,你是否会觉得这段代码真是高大上呢? 或许只有我这种小白才会这样子觉得,就在刚刚,我就看见了别人的代码中的yield,觉 ...
- Python中的yield生成器的简单介绍
Python yield 使用浅析(整理自:廖 雪峰, 软件工程师, HP 2012 年 11 月 22 日 ) 初学 Python 的开发者经常会发现很多 Python 函数中用到了 yield 关 ...
随机推荐
- 盘一盘Tidyverse| 筛行选列之select,玩转列操作
原文链接:https://mp.weixin.qq.com/s/ldO0rm3UM_rqlFnU3euYaA 2020年,开封 <R 数据科学>R for data science,系统学 ...
- 数据结构——栈的应用 NOI2.2 括号匹配问题
栈是一种数据结构,相当于一个容器,将一个又一个变量从顶端压进去,需要使用时,又从顶端拿出来,其具体使用方法,下面是详细讲解: #include<stack>必须使用此头文件 stack&l ...
- Dynamics CRM Package Deployer 部署工具
CRM 部署工具非常有用 我们可以用部署工具来做迁移,部署 等等. Package Deployer可以同时部署多个solutions. 并且也可以勾选solution的plugin也同时部署. 三 ...
- Linux程序守护脚本
不废话,直接上脚本,[]注释的下发语句需要按需替换: #!/usr/bin/env bash PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/us ...
- xpath写法大全(适用于selenium、robotframework)
1.//input[contains(@id, 'txttags')] 定位出来是个ID,但是ID后面的“102”是个随机数,所以用定位ID的方法就不行了,用firepath生成的xpath也会包括这 ...
- Jmeter之BeanShell断言使用
1.Bean Shell常用内置变量 JMeter在它的BeanShell中内置了变量,用户可以通过这些变量与JMeter进行交互,其中主要的变量及其使用方法如下: log:用来记录日志文件,写入到j ...
- CSS-04-层叠选择器
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 笔记常用Linux命令(二) 进程和端口
查看系统进程 ps:用于报告当前系统的进程状态 a:显示所有终端机下执行的程序 ps -ef/ps aux: 这两个命令都是查看当前系统正在运行进程,两者的区别是展示格式不同. 如果想要查看特定的进程 ...
- Python里的装饰器
装饰器 装饰器是干什么用的? 装饰器可以在不修改某个函数的情况下,给函数添加功能. 形象点来说,从前有一个王叔叔,他一个人住在家里,每天打扫家,看书.于是定义如下一个函数: def uncle_wan ...
- 10个很多人不知道的Redis使用技巧
前言 Redis 在当前的技术社区里是非常热门的.从来自 Antirez 一个小小的个人项目到成为内存数据存储行业的标准,Redis已经走过了很长的一段路.随之而来的一系列最佳实践,使得大多数人可以正 ...