Java多线程

一、volatile

  1. 保证线程可见性
    java堆内存是线程间共享的,除此之外各线程有自己的独享内存。线程读写共享的内存时,会有经历"复制->修改->回写"过程,这导致了线程间的数据不可见。
    volatile能保证线程间的可见,一个线程的修改能够立即被其他线程看见。
    1.1 拓展:
    • MESI: 本质上使用了CPU的"高速缓冲一致性"协议.
    • volatile:hotspot JVM的实现是由总线锁实现的.
    • 硬件级"数据一致性"与volatile没有关系,volatile是由JVM保证的,而所有CPU硬件都会保证"数据一致性",有多种实现方式.
  2. 禁止指令重排序
    CPU执行指令并不是严格顺序执行的,而是并发执行,第一条指令没有执行完毕,第二条指令可能已经执行了,这称为流水线执行。这是CPU提高执行效率的一种方式。为了充分利用CPU的优势,编译器可能会将本来顺序执行的指令交换顺序。例如:
/*volatile*/ int a = 1, b = 0;
a++; // (1)
b++; // (2)

指令(1)和(2)很可能就被交换顺序。CPU的指令重排需要满足“最终一致性”。

二、CPU的数据一致性

CPU保证数据一致性,有多种实现方法:

  1. 关中断

  2. 缓存一致性协议
    2.1 存储器速度
    寄存器 > 一级缓存(CPU内部) > 二级缓存 > 三级缓存 > 内存 > 外存。
    寄存器比外存快100倍。

    2.2 多级缓存
    多级缓存示意图
    如上图所示,目前一般采用三级缓存,缓存行64 KB。所谓“缓存行”就是一次加载进入缓存的数据大小。
    缓存命中:CPU首先在一级缓存中找,然后进入二级缓存中找,找不到再找三级缓存,最后找内存。加载数据过程则相反。

    2.3 缓存一致性协议
    概念:保证不同CPU核心内的缓存一致性。
    这是一种协议,具体实现方法有多种,例如“缓存锁”(或者称为“总线锁”)。
    举例

    • MESI:Intel CPU的协议
    • MOSI
    • MSI
  3. 系统屏障

  4. 总线锁/缓存锁

三、synchronized

3.1 Java对象组成
Java对象内存快照
一个JAVA普通对象由以上4部分构成:

  • markword:标记字(8 bytes),记录对象有关信息;
  • 类型指针:一般为4 bytes,指向对应的.class文件,比如T t = new T(); 那么对象t中的类型指针指向T.class文件。第1和第2部分称为“对象头”。
  • 实例数据:就是对象的属性成员;
  • 对齐(填充):JAVA对象8 bytes对齐。填充就像集装箱,大家都是一样的大小,处理起来比较方便。

3.2 synchronized使用方法
synchronized本质是锁定对象,即使是synchronized(T.class),锁定的也是T.class这个二进制文件。

  • synchronized(Object)
    举例:
public class T {
	private Object object1;
	public void fun1() {
		// 一些逻辑
		synchronized(object1) {
			// 临界区
			fun3();
		}
		// 一些逻辑
	}
	public void fun2() {
		// 一些逻辑
		synchronized(object2) {
			// 临界区
			fun3();
		}
		// 一些逻辑
	}
	public void fun3() {
		// 无锁
	}
}

锁住的是对象object。
synchronized会在对象object1、object2的markword写上对应的线程ID等信息。
注意:fun1()和fun2()是可以同时运行的,因为他们锁定的是不同的对象;持锁线程是可以同时调用无锁函数的,也就是说临界区代码和无锁代码之间相互也不影响。

  • synchronized(T.class)
public class T {
	public void fun() {
		// 一些逻辑
		synchronized(T.class) {
			// 临界区
		}
		// 一些逻辑
	}
}

锁住的是T.class这个二进制文件。ClassLoader将T.class加载进来才能运行,并且这个T.class在同一个ClassLoader中是唯一的,而不同的ClassLoader之间也不能相互访问。故所有T的对象都必须争用同一把锁。

  • synchronized fun()
class T {
	synchronized public void fun() {
		// 一些逻辑
	}
}

本质上锁定的是对象。

  • synchronized(static_object)
class T {
	static final Object object; // 一般用
}

3.3 synchronized底层实现
synchronized的代码会经历一个锁升级的过程,以synchroinze(Object)为例:

  • 偏向锁 第一阶段:使用偏向锁,内部实现为仅仅在Java Object的markword中记录这个线程的ID。因为不一定会有其他线程会争用,没有必要真正去锁定临界区。
  • 自旋锁 第二阶段:如果有线程争用,那么升级为自旋锁,自旋锁不会释放CPU,不会进入就绪队列,用一个while在那自旋等待CPU。
  • 重量级锁 如果自旋10次以后,还是无法得到锁,那么升级为重量级锁,释放CPU,向操作系统申请资源,进去就绪队列,交给操作系统调度。

3.4 synchronized性质

  • 可重入锁

问题

  1. 单CPU多线程有没有意义?
    答:有意义。因为IO线程不消耗CPU,哪怕成千上万个IO线程都行,对于有IO操作完全可以另外开辟一个线程去执行,这样CPU可以充分被利用。

  2. 一个核数为8的CPU,IO操作时间占比为1/5,计算任务时间占比为4/5,应该开辟多少线程?
    答:IO操作时间:计算任务时间 = 1:4,这样可以开辟4个线程,1个用来执行IO线程,3个用来执行计算任务。因为IO操作不消耗CPU,那么当IO操作执行时,其他计算任务可以来执行,让CPU执行效率达到100%.

  3. 全新的界面设计 ,将会带来全新的写作体验;

  4. 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;

  5. 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;

  6. 全新的 KaTeX数学公式 语法;

  7. 增加了支持甘特图的mermaid语法1 功能;

  8. 增加了 多屏幕编辑 Markdown文章功能;

  9. 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;

  10. 增加了 检查列表 功能。

功能快捷键

撤销:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜体:Ctrl/Command + I
标题:Ctrl/Command + Shift + H
无序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
检查列表:Ctrl/Command + Shift + C
插入代码:Ctrl/Command + Shift + K
插入链接:Ctrl/Command + Shift + L
插入图片:Ctrl/Command + Shift + G
查找:Ctrl/Command + F
替换:Ctrl/Command + G

合理的创建标题,有助于目录的生成

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

强调文本 强调文本

加粗文本 加粗文本

标记文本

删除文本

引用文本

H2O is是液体。

210 运算结果是 1024.

插入链接与图片

链接: link.

图片: Alt

带尺寸的图片: Alt

居中的图片: Alt

居中并且带尺寸的图片: Alt

当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。

如何插入一段漂亮的代码片

博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
var foo = 'bar';

生成一个适合你的列表

  • 项目
    • 项目
      • 项目
  1. 项目1
  2. 项目2
  3. 项目3
  • 计划任务
  • 完成任务

创建一个表格

一个简单的表格是这么创建的:

项目Value
电脑$1600
手机$12
导管$1

设定内容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列第二列第三列
第一列文本居中第二列文本居右第三列文本居左

SmartyPants

SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如:

TYPEASCIIHTML
Single backticks'Isn't this fun?'‘Isn’t this fun?’
Quotes"Isn't this fun?"“Isn’t this fun?”
Dashes-- is en-dash, --- is em-dash– is en-dash, — is em-dash

创建一个自定义列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何创建一个注脚

一个具有注脚的文本。2

注释也是必不可少的

Markdown将文本转换为 HTML

KaTeX数学公式

您可以使用渲染LaTeX数学表达式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n − 1 ) ! ∀ n ∈ N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N Γ(n)=(n1)!nN 是通过欧拉积分

Γ ( z ) = ∫ 0 ∞ t z − 1 e − t d t   . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. Γ(z)=0tz1etdt.

你可以找到更多关于的信息 LaTeX 数学表达式here.

新的甘特图功能,丰富你的文章

Mon 06 Mon 13 Mon 20 已完成 进行中 计划一 计划二 现有任务 Adding GANTT diagram functionality to mermaid
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图:

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

Created with Raphaël 2.3.0 开始 我的操作 确认? 结束 yes no
  • 关于 Flowchart流程图 语法,参考 这儿.

  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值