Happens before

简介:

原文:http://www.cs.umd.edu/class/fall2010/cmsc433/lectures/happens-before.txt

译者:丁一

“Happens before”是由Leslie Lamport引入的用来描述程序事件的一种偏序关系。

将多线程的执行看作是事件E的轨迹R,定义如下(轨迹只是一种次序):


Events E ::= start(T)
	  |  end(T)
	  |  read(T,x,v)
  	|  write(T,x,v)
	  |  spawn(T1,T2)
	  |  join(T1,T2)
	  |  lock(T,x)
	  |  unlock(T,x)


这里T是一个线程标识符,x是一个变量,v是一个值。read(T,x,v)事件表示线程T从变量x中读出值v。同时假定轨迹R是结构良好的,即要求在R中,线程T的第一个事件必须是start(T)。在end(T)之后不再有线程T相关的事件。

设E1 < E2为E1和E2在轨迹中出现的顺序,它是可传递的、反自反的和反对称的。定义轨迹R中的happens-before次序(<:)如下:
E1 <: E2,当且仅当E1 < E2,且下列条件之一成立:


  a) thread(E1) = thread(E2)
  b) E1为spawn(T1,T2), E2为start(T2)
  c) E2为join(T1,T2),E1为end(T2)
  d) E1为unlock(T1,x),E2为lock(T2,x)
  e) 存在这样的E3:E1 <: E3 且 E3 <: E2 (即,happens-before次序是可传递的)


可见性
假设轨迹R中有EW == write(T1,x,v1) 和 ER == read(T2,x,v2),如果:
a) ER <: EW (即,读事件与写事件间有happens-before次序)
b) 存在一个介入的事件EW2 == write(T,x,v3),有EW <: EW2 <: R (即,第一次写的值被第二次覆盖了)

则,EW对ER不可见(即v1 != v2)。否则,EW对ER可见,ER中的读操作就能看的见EW中写入的值。例如:


 (起始 x = 0)
Thread 1:      Thread 2:
x = 1;         y = x;
y = 2;


这是一些可能的轨迹:


R1 == write(T1,x,1); read(T2,x,0); write(T2,y,0); write(T1,y,2)
R2 == write(T1,x,1); read(T2,x,1); write(T2,y,1); write(T1,y,2)
R3 == read(T2,x,0); write(T1,x,1); write(T2,y,0); write(T1,y,2)
R4 == write(T1,x,1); read(T2,x,1); write(T1,y,2); write(T2,y,1)
R5 == read(T2,x,0); write(T1,x,1); write(T1,y,2); write(T2,y,0)


注意在轨迹R1中,T2读取x获得的值是0;这是合理的,因为轨迹中x=1和x=2在那个时刻都是可见的;这是由于T1写值到x中没有”happen before”读操作。轨迹R2读得1。在轨迹R3中,T2线程的读操作先发生,所以它能读到的唯一可能的值就是x的初始值:0. 轨迹R4和R5分别类同于R2和R3,只是最后两个事件的顺序颠倒了。这些轨迹展示了y的最终结果,如果运行该程序,可能为0,1或2.

再来一个例子:


 (起始 x = 0)
Thread 1:      Thread 2:
lock(y);       lock(y);
x = 1;         x = x + 1;
unlock(y);     unlock(y);


下面是两个可能的轨迹:


R1 == lock(T1,y); write(T1,x,1); unlock(T1,y);
      lock(T2,y); read(T2,x,1); write(T2,x,2); unlock(T2,y)

R2 == lock(T2,y); read(T2,x,0); write(T2,x,1); unlock(T2,y)
      lock(T1,y); write(T1,x,1); unlock(T1,y);


在第一个轨迹中,线程T2从x中读得1。这是因为write(T1,x,1)先于read(T2,x,1)发生—这两个事件因为unlock(T1,y) <:lock(T2,y)以及传递性的存在而成为有序的。这个时刻T2不可能读到0。另一个轨迹中T2首先获得锁。

数据争用
有了happens-before次序,就可以准确地定义数据争用:轨迹R中的两个事件,其中至少有一个写事件,访问同一块内存区域,根据happens-before规则它们是无序的,就会发生数据争用。接下来有几个例子,第一个例子跟上面的一样:


 (起始 x = 0)
Thread 1:      Thread 2:
x = 1;         y = x;
y = 2;


对于这两个线程任何可能的执行,线程对x、y的写操作 与 线程2读取x、写入y之间没有次序关系。这样就形成了数据争用。这里有一个可能的轨迹,E11 == write(T1,x,1), E21 == read(T2,x,0), E22 == write(T2,y,0)以及 E12 = write(T1,y,2):
轨迹R == E11; E21; E22; E12

在这个轨迹中,E11和E21形成了数据争用:它们没有被happens-before排序,然后访问了同一个变量,其中E11事件是一个写操作。其它的数据争用包括E11和E22之间,E12和E21之间以及E12和E22之间。

再来一个例子:


Thread 1:      Thread 2:
lock y;        print(x);
x = 1;
unlock y;


这里线程2的读事件(为了print)与线程1的写事件之间仍然存在数据争用。下面是一个可能的轨迹:
lock(T1,y); write(T1,x,1); unlock(T1,y); read(T2,x,0)

在这个轨迹中,write(T1,x,1)事件与read(T2,x,1)事件之间存在数据争用,因为这两个事件没有被happens-before排序。这是由于,尽管在这个轨迹中实际上是有顺序的( < 顺序),但是它们位于不同的线程中且它们之间没有同步事件。这个程序所有可能的轨迹都有这种争用。注意上面的轨迹中,读和写事件没有在同一时刻发生–在轨迹中它们只是无序的。

下面这个程序有时会表现出争用:


Thread 1:      Thread 2:
x = 1;         lock y;
lock y;        unlock y; 
unlock y;      print(x);


这个例子中,下面的轨迹不存在数据争用:
write(T1,x,1); lock(T1,y); unlock(T1,y); lock(T2,y); unlock(T2,y); read(T2,x,1)

在这种情况下,读和写事件被happens before排序了,因为根据前面的规则unlock(T1,y) <: lock(T2,y),所有其它的事件被轨迹顺序 < 排序,加上传递性,就有了write(T1,x,1) <: read(T2,x,1),所以没有争用。

下面这个轨迹确实展示了一种争用:
lock(T2,y); unlock(T2,y); write(T1,x,1); read(T2,x,0); lock(T1,y); unlock(T1,y)

这里,写事件和读事件没有被happens-before排序,因此形成了争用。 

目录
相关文章
|
8月前
|
IDE Java Shell
Java的开发环境的搭建
Java的开发环境的搭建
|
存储 安全 数据安全/隐私保护
13 Tornado - Cookie
13 Tornado - Cookie
62 2
|
缓存 分布式计算 Java
Hbase性能优化
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tomnic_ylwang/article/details/81105619 一、性能优化 1.
1728 0
|
14天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171332 12
|
17天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150295 32
|
25天前
|
弹性计算 人工智能 安全
对话 | ECS如何构筑企业上云的第一道安全防线
随着中小企业加速上云,数据泄露、网络攻击等安全威胁日益严重。阿里云推出深度访谈栏目,汇聚产品技术专家,探讨云上安全问题及应对策略。首期节目聚焦ECS安全性,提出三道防线:数据安全、网络安全和身份认证与权限管理,确保用户在云端的数据主权和业务稳定。此外,阿里云还推出了“ECS 99套餐”,以高性价比提供全面的安全保障,帮助中小企业安全上云。
201962 14
对话 | ECS如何构筑企业上云的第一道安全防线
|
3天前
|
机器学习/深度学习 自然语言处理 PyTorch
深入剖析Transformer架构中的多头注意力机制
多头注意力机制(Multi-Head Attention)是Transformer模型中的核心组件,通过并行运行多个独立的注意力机制,捕捉输入序列中不同子空间的语义关联。每个“头”独立处理Query、Key和Value矩阵,经过缩放点积注意力运算后,所有头的输出被拼接并通过线性层融合,最终生成更全面的表示。多头注意力不仅增强了模型对复杂依赖关系的理解,还在自然语言处理任务如机器翻译和阅读理解中表现出色。通过多头自注意力机制,模型在同一序列内部进行多角度的注意力计算,进一步提升了表达能力和泛化性能。
|
7天前
|
存储 人工智能 安全
对话|无影如何助力企业构建办公安全防护体系
阿里云无影助力企业构建办公安全防护体系
1253 8
|
8天前
|
人工智能 自然语言处理 程序员
通义灵码2.0全新升级,AI程序员全面开放使用
通义灵码2.0来了,成为全球首个同时上线JetBrains和VSCode的AI 程序员产品!立即下载更新最新插件使用。
1306 24
|
9天前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。