CN111522730B - 程序测试方法及装置、计算机装置、计算机可读介质 - Google Patents
程序测试方法及装置、计算机装置、计算机可读介质 Download PDFInfo
- Publication number
- CN111522730B CN111522730B CN202010158772.3A CN202010158772A CN111522730B CN 111522730 B CN111522730 B CN 111522730B CN 202010158772 A CN202010158772 A CN 202010158772A CN 111522730 B CN111522730 B CN 111522730B
- Authority
- CN
- China
- Prior art keywords
- lock
- thread scheduling
- sequence
- thread
- execution
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
- 238000000034 method Methods 0.000 claims abstract description 24
- 238000004590 computer program Methods 0.000 claims description 22
- 238000012360 testing method Methods 0.000 claims description 13
- 238000012790 confirmation Methods 0.000 claims description 7
- 238000012545 processing Methods 0.000 claims description 7
- 230000006870 function Effects 0.000 description 9
- 238000010586 diagram Methods 0.000 description 5
- 238000011010 flushing procedure Methods 0.000 description 2
- 230000007246 mechanism Effects 0.000 description 2
- 238000012544 monitoring process Methods 0.000 description 2
- 238000003491 array Methods 0.000 description 1
- 238000004364 calculation method Methods 0.000 description 1
- 238000013461 design Methods 0.000 description 1
- 238000005516 engineering process Methods 0.000 description 1
- 230000010365 information processing Effects 0.000 description 1
- 230000003993 interaction Effects 0.000 description 1
- 238000012986 modification Methods 0.000 description 1
- 230000004048 modification Effects 0.000 description 1
- 230000003287 optical effect Effects 0.000 description 1
- 238000012552 review Methods 0.000 description 1
- 239000007787 solid Substances 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3604—Software analysis for verifying properties of programs
- G06F11/3612—Software analysis for verifying properties of programs by runtime analysis
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/46—Multiprogramming arrangements
- G06F9/52—Program synchronisation; Mutual exclusion, e.g. by means of semaphores
- G06F9/524—Deadlock detection or avoidance
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Software Systems (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Computer Hardware Design (AREA)
- Quality & Reliability (AREA)
- Debugging And Monitoring (AREA)
- Executing Machine-Instructions (AREA)
Abstract
本发明提供了一种程序测试方法及装置、计算机装置、计算机可读存储介质。所述方法获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;从所述锁申请序列中查找所述被测试程序的锁环路数组;判断所述锁环路数组是否有效;若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。本发明提升了检测潜在死锁的效率。
Description
技术领域
本发明涉及测试技术领域,具体涉及一种程序测试方法及装置、计算机装置、计算机可读存储介质。
背景技术
当前的应用环境中的绝大部分程序支持多线程机制,多线程机制可以帮助程序提升完成任务的效率。但是,在程序的运行过程中,程序对多线程的调度具有不确定性;当程序的部分线程申请的锁被其他线程持有时,便会发生死锁。死锁是一种常见的多线程并发错误,死锁一旦发生,程序就有很大可能无法继续正常提供服务。
通常,在程序发布前的评审阶段,对程序进行评审以检查程序中的死锁问题,由于程序的设计和编码都比较复杂,程序对多个线程的调用关系数量庞大,导致难以找出潜在死锁。在程序发布前的测试阶段也难以发现死锁,因为只有当程序执行特定的线程调度顺序时,死锁才会发生。而程序在测试过程中随机调度线程,导致有可能不能检测出死锁。
发明内容
鉴于以上内容,有必要提出一种程序测试方法及装置、计算机装置计算机可读存储介质,其可以检测程序中的潜在死锁。
本申请的第一方面提供一种程序测试方法,所述方法包括:
获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断所述锁环路数组是否有效;
若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
另一种可能的实现方式中,所述获取被测试程序的线程调度序列包括:
根据所述被测试程序的线程和执行路径生成多个被测试子程序;
获取每个被测试子程序的线程调度子序列,得到多个线程调度子序列,每个线程调度子序列包括一个或多个依执行顺序组成的线程调度指令;
对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列。
另一种可能的实现方式中,所述根据所述线程调度序列生成锁申请序列包括:
从所述线程调度序列中依所述执行索引的顺序读取每个执行线程的线程调度指令,将读取的每个执行线程的线程调度指令依次组合为每个执行线程的线程调度子序列;
生成每个线程调度子序列的一个或多个连续锁申请元素;
组合所述多个线程调度子序列的一个或多个连续锁申请元素,得到所述锁申请序列。
另一种可能的实现方式中,所述生成每个线程调度子序列的一个或多个连续锁申请元素包括:
初始化第一集合和第二集合;
从该线程调度子序列的第一个线程调度指令开始,对每一个线程调度指令执行以下步骤:
判断该线程调度指令的执行类型;
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,将该线程调度指令的执行对象加入所述第一集合;
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,将该线程调度指令的执行对象作为第一锁对象,将所述第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象确定为第二锁对象,将所述第二锁对象加入所述第二集合,生成一个连续锁申请元素,该连续锁申请元素包括该线程调度指令的待执行线程、所述第二锁对象、所述第一锁对象、该线程调度指令的执行索引、所述第二锁对象所属的线程调度指令的执行索引和所述第二集合的锁对象;
若该线程调度指令的执行类型为解锁类型,将该线程调度指令的执行对象确定为第三锁对象,若所述第一集合中存在与所述第三锁对象一致的锁对象,删除所述第一集合中的与所述第三锁对象一致的锁对象,若所述第二集合中存在与所述第三锁对象一致的锁对象,删除所述第二集合中的与所述第三锁对象一致的锁对象;
若该线程调度指令是该线程调度子序列的最后一个线程调度指令,清空所述第一集合和所述第二集合。
另一种可能的实现方式中,所述从所述锁申请序列中查找所述被测试程序的锁环路数组包括:
创建锁环路栈、第三集合和锁对象变量,对所述锁申请序列中的每个连续锁申请元素设置读取标识符,所述读取标识符的初始值为0;
从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第i个连续锁申请元素Ai为起点的所述锁环路数组,1≤i≤n,n为所述锁申请序列中的连续锁申请元素的数量:
将Ai对所述锁环路栈进行入栈,将Ai的待执行线程加入所述第三集合,将Ai的读取标识符设置为1,将Ai的第一锁对象赋值给所述锁对象变量;
若所述锁环路栈不为空,从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第j个连续锁申请元素Aj为结束点的所述锁环路数组,其中1≤j≤n:
判断Aj的第二锁对象与所述锁对象变量的值是否一致且Aj的读取标识符是否为0;
若Aj的第二锁对象与所述锁对象变量的值一致且Aj的读取标识符为0,将Aj对所述锁环路栈进行入栈,将Aj的待执行线程加入所述第三集合,将Aj的标识符设置为1,将Aj的第一锁对象赋值给所述锁对象变量;
判断Aj的第一锁对象与Ai的第二锁对象是否一致且所述第三集合中的待执行线程是否一致;
若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程不一致,确定所述锁环路栈中的连续锁申请元素为以Ai为起点以Aj为结束点的所述锁环路数组。
另一种可能的实现方式中,所述判断所述锁环路数组是否有效包括:
若所述锁环路数组中待执行线程相同的连续锁申请元素之间不存在环路缺口,且所述锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路,则所述锁环路数组有效;
若所述锁环路数组中待执行线程相同的连续锁申请元素之间存在环路缺口,或所述锁环路数组中待执行线程不同的连续锁申请元素之间存在门锁环路,则所述锁环路数组无效。
另一种可能的实现方式中,所述根据所述锁环路数组调整所述线程调度序列包括:
将所述线程调度序列的线程调度指令的执行索引设置为1;
若所述线程调度序列的给定线程调度指令的待执行线程与所述锁环路数组的给定连续锁申请元素的待执行线程一致、所述线程调度序列的给定线程调度指令的执行对象与所述锁环路数组的给定连续锁申请元素的第一锁对象一致且所述线程调度序列的给定线程调度指令的执行类型为加锁类型,则所述线程调度序列的给定线程调度指令与所述锁环路数组的给定连续锁申请元素一一对应,在所述线程调度序列中将所述给定线程调度指令的执行索引设置为-1;
若所述线程调度序列中的除所述给定线程调度指令外的目标线程调度指令位于所述给定线程调度指令之后且待执行线程与所述给定线程调度指令的待执行线程一致,或若所述线程调度序列的目标线程调度指令之后不存在所述给定线程调度指令,则将所述目标线程调度指令的执行索引设置为0;
删除执行索引为0的线程调度指令,将执行索引为0的线程调度指令移动至所述线程调度序列的尾部。
本申请的第二方面提供一种程序测试装置,所述装置包括:
获取模块,用于获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
生成模块,用于根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
查找模块,用于从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断模块,用于判断所述锁环路数组是否有效;
调整模块,用于若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
确认模块,用于按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
另一种可能的实现方式中,所述获取被测试程序的线程调度序列包括:
根据所述被测试程序的线程和执行路径生成多个被测试子程序;
获取每个被测试子程序的线程调度子序列,得到多个线程调度子序列,每个线程调度子序列包括一个或多个依执行顺序组成的线程调度指令;
对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列。
另一种可能的实现方式中,所述根据所述线程调度序列生成锁申请序列包括:
从所述线程调度序列中依所述执行索引的顺序读取每个执行线程的线程调度指令,将读取的每个执行线程的线程调度指令依次组合为每个执行线程的线程调度子序列;
生成每个线程调度子序列的一个或多个连续锁申请元素;
组合所述多个线程调度子序列的一个或多个连续锁申请元素,得到所述锁申请序列。
另一种可能的实现方式中,所述生成每个线程调度子序列的一个或多个连续锁申请元素包括:
初始化第一集合和第二集合;
从该线程调度子序列的第一个线程调度指令开始,对每一个线程调度指令执行以下步骤:
判断该线程调度指令的执行类型;
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,将该线程调度指令的执行对象加入所述第一集合;
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,将该线程调度指令的执行对象作为第一锁对象,将所述第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象确定为第二锁对象,将所述第二锁对象加入所述第二集合,生成一个连续锁申请元素,该连续锁申请元素包括该线程调度指令的待执行线程、所述第二锁对象、所述第一锁对象、该线程调度指令的执行索引、所述第二锁对象所属的线程调度指令的执行索引和所述第二集合的锁对象;
若该线程调度指令的执行类型为解锁类型,将该线程调度指令的执行对象确定为第三锁对象,若所述第一集合中存在与所述第三锁对象一致的锁对象,删除所述第一集合中的与所述第三锁对象一致的锁对象,若所述第二集合中存在与所述第三锁对象一致的锁对象,删除所述第二集合中的与所述第三锁对象一致的锁对象;
若该线程调度指令是该线程调度子序列的最后一个线程调度指令,清空所述第一集合和所述第二集合。
另一种可能的实现方式中,所述从所述锁申请序列中查找所述被测试程序的锁环路数组包括:
创建锁环路栈、第三集合和锁对象变量,对所述锁申请序列中的每个连续锁申请元素设置读取标识符,所述读取标识符的初始值为0;
从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第i个连续锁申请元素Ai为起点的所述锁环路数组,1≤i≤n,n为所述锁申请序列中的连续锁申请元素的数量:
将Ai对所述锁环路栈进行入栈,将Ai的待执行线程加入所述第三集合,将Ai的读取标识符设置为1,将Ai的第一锁对象赋值给所述锁对象变量;
若所述锁环路栈不为空,从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第j个连续锁申请元素Aj为结束点的所述锁环路数组,其中1≤j≤n:
判断Aj的第二锁对象与所述锁对象变量的值是否一致且Aj的读取标识符是否为0;
若Aj的第二锁对象与所述锁对象变量的值一致且Aj的读取标识符为0,将Aj对所述锁环路栈进行入栈,将Aj的待执行线程加入所述第三集合,将Aj的标识符设置为1,将Aj的第一锁对象赋值给所述锁对象变量;
判断Aj的第一锁对象与Ai的第二锁对象是否一致且所述第三集合中的待执行线程是否一致;
若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程不一致,确定所述锁环路栈中的连续锁申请元素为以Ai为起点以Aj为结束点的所述锁环路数组。
另一种可能的实现方式中,所述判断所述锁环路数组是否有效包括:
若所述锁环路数组中待执行线程相同的连续锁申请元素之间不存在环路缺口,且所述锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路,则所述锁环路数组有效;
若所述锁环路数组中待执行线程相同的连续锁申请元素之间存在环路缺口,或所述锁环路数组中待执行线程不同的连续锁申请元素之间存在门锁环路,则所述锁环路数组无效。
另一种可能的实现方式中,所述根据所述锁环路数组调整所述线程调度序列包括:
将所述线程调度序列的线程调度指令的执行索引设置为1;
若所述线程调度序列的给定线程调度指令的待执行线程与所述锁环路数组的给定连续锁申请元素的待执行线程一致、所述线程调度序列的给定线程调度指令的执行对象与所述锁环路数组的给定连续锁申请元素的第一锁对象一致且所述线程调度序列的给定线程调度指令的执行类型为加锁类型,则所述线程调度序列的给定线程调度指令与所述锁环路数组的给定连续锁申请元素一一对应,在所述线程调度序列中将所述给定线程调度指令的执行索引设置为-1;
若所述线程调度序列中的除所述给定线程调度指令外的目标线程调度指令位于所述给定线程调度指令之后且待执行线程与所述给定线程调度指令的待执行线程一致,或若所述线程调度序列的目标线程调度指令之后不存在所述给定线程调度指令,则将所述目标线程调度指令的执行索引设置为0;
删除执行索引为0的线程调度指令,将执行索引为0的线程调度指令移动至所述线程调度序列的尾部。
本申请的第三方面提供一种计算机装置,所述计算机装置包括处理器,所述处理器用于执行存储器中存储的计算机程序时实现所述程序测试方法。
本申请的第四方面提供一种计算机可读存储介质,其上存储有计算机程序,所述计算机程序被处理器执行时实现所述程序测试方法。
本发明检测程序中的潜在死锁,提升了检测潜在死锁的效率。
附图说明
图1是本发明实施例提供的程序测试方法的流程图。
图2是本发明实施例提供的程序测试装置的结构图。
图3是本发明实施例提供的计算机装置的示意图。
具体实施方式
为了能够更清楚地理解本发明的上述目的、特征和优点,下面结合附图和具体实施例对本发明进行详细描述。需要说明的是,在不冲突的情况下,本申请的实施例及实施例中的特征可以相互组合。
在下面的描述中阐述了很多具体细节以便于充分理解本发明,所描述的实施例仅仅是本发明一部分实施例,而不是全部的实施例。基于本发明中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本发明保护的范围。
除非另有定义,本文所使用的所有的技术和科学术语与属于本发明的技术领域的技术人员通常理解的含义相同。本文中在本发明的说明书中所使用的术语只是为了描述具体的实施例的目的,不是旨在于限制本发明。
优选地,本发明的程序测试方法应用在一个或者多个计算机装置中。所述计算机装置是一种能够按照事先设定或存储的指令,自动进行数值计算和/或信息处理的设备,其硬件包括但不限于微处理器、专用集成电路(Application Specific IntegratedCircuit,ASIC)、可编程门阵列(Field-Programmable Gate Array,FPGA)、数字处理器(Digital Signal Processor,DSP)、嵌入式设备等。
所述计算机装置可以是桌上型计算机、笔记本、掌上电脑及云端服务器等计算设备。所述计算机装置可以与用户通过键盘、鼠标、遥控器、触摸板或声控设备等方式进行人机交互。
实施例一
图1是本发明实施例一提供的程序测试方法的流程图。所述程序测试方法应用于计算机装置。
本发明程序测试方法用于检测程序中的潜在死锁。
如图1所示,所述程序测试方法包括:
101,获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引。
在一具体实施例中,所述获取被测试程序的线程调度序列包括:
根据所述被测试程序的线程和执行路径生成多个被测试子程序;
获取每个被测试子程序的线程调度子序列,得到多个线程调度子序列,每个线程调度子序列包括一个或多个依执行顺序组成的线程调度指令;
对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列。
例如,给定被测试程序存在二个线程(即两个主体代码),第一个线程存在两个执行路径“a-b”和“a-c”,第二个线程存在两个执行路径“d-e”和“d-f”,生成四个被测试子程序,四个被测试子程序的执行路径分别为:“a-b”、“a-c”、“d-e”和“d-f”;获取每个被测试子程序的线程调度子序列为:“T1{L(A)}1-T1{L(B)}2”、“T1{L(A)}1-T1{L(C)}2”、“T2{L(D)}1-T1{L(E)}2”、“T2{L(D)}1-T1{L(F)}2”,其中,T1、T2为待执行线程,“L()”为执行类型(表示lock,执行类型为加锁类型),A、B、C、D、E、F为执行对象,1和2为执行索引;对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列“T1{L(A)}1-T1{L(B)}2-T2{L(D)}3-T1{L(E)}4”、“T1{L(A)}1-T1{L(B)}2-T2{L(D)}3-T1{L(F)}4”、“T1{L(A)}1-T1{L(C)}2-T2{L(D)}3-T1{L(E)}4”或“T1{L(A)}1-T1{L(C)}2-T2{L(D)}3-T1{L(F)}4”。
在另一实施例中,所述获取每个被测试子程序的线程调度序列包括:
在该被测试子程序的可执行代码中插入监视代码;
执行该被测试子程序,使通过执行该子监视代码在该被测试子程序的内存空间记录线程调度指令;
依执行顺序存储线程调度指令,得到所述线程调度子序列。
102,根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成。
在一具体实施例中,所述根据所述线程调度序列生成锁申请序列包括:
(A)从所述线程调度序列中依所述执行索引的顺序读取每个执行线程的线程调度指令,将读取的每个执行线程的线程调度指令依次组合为每个执行线程的线程调度子序列。
例如,线程调度序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6-T2{L(G)}7-T2{L(A)}8-T2{L(B)}9-T2{U(B)}10-T2{U(A)}11-T2{U(G)}12”,其中“U()”为执行类型(表示unlock,执行类型为解锁类型),G为执行对象。分别读取执行线程为T1和T2的线程调度指令,将执行线程T1的线程调度指令依次组合为执行线程T1的线程调度子序列,将执行线程T2的线程调度指令依次组合为执行线程T2的线程调度子序列,两个线程调度子序列分别为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,“T2{L(G)}7-T2{L(A)}8-T2{L(B)}9-T2{U(B)}10-T2{U(A)}11-T2{U(G)}12”。
(B)生成每个线程调度子序列的一个或多个连续锁申请元素。
在一具体实施例中,所述生成每个线程调度子序列的一个或多个连续锁申请元素包括:
(1)初始化第一集合和第二集合。
(2)从该线程调度子序列的第一个线程调度指令开始,对每一个线程调度指令执行以下步骤:
(2.1)判断该线程调度指令的执行类型。
(2.1.1)若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,将该线程调度指令的执行对象加入所述第一集合。
例如,线程调度子序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,第一集合和第二集合为空集,读取第一个线程调度指令“T1{L(A)}1”,该线程调度指令的执行类型为加锁类型(L)且第一集合中的锁对象的数量小于1,将锁对象A加入第一集合。
(2.1.2)若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,将该线程调度指令的执行对象作为第一锁对象,将所述第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象确定为第二锁对象,将所述第二锁对象加入所述第二集合,生成一个连续锁申请元素,该连续锁申请元素包括该线程调度指令的待执行线程、所述第二锁对象、所述第一锁对象、该线程调度指令的执行索引、所述第二锁对象所属的线程调度指令的执行索引和所述第二集合的锁对象。
例如,线程调度子序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,第一集合包括锁对象A,第二集合为空集,读取第二个线程调度指令“T1{L(B)}2”,该线程调度指令的执行类型为加锁类型(L)且第一集合中的锁对象的数量等于1,将B确定为第一锁对象,将第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象(锁对象A)确定为第二锁对象,其中锁对象A所属的线程调度指令(T1{L(A)}1)的执行索引为1,该线程调度指令(T1{L(B)}2)的执行索引为2。将第二锁对象(锁对象A)加入第二集合。生成的连续锁申请元素为“T1-(A,B)-(1,2)-{A}”,其中,T1为该线程调度指令的待执行线程,A为第二锁对象,B为第一锁对象,1为第二锁对象所属的线程调度指令的执行索引,2为该线程调度指令的执行索引,{A}为第二集合的锁对象。
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,说明该线程调度指令的待执行线程至少存在一次连续加锁操作,因此将所述第二锁对象加入所述第二集合,表示该线程调度指令的待执行线程持有所述第二锁对象(即如果另一线程需要持有所述第二锁对象,需等待该线程调度指令的待执行线程解锁所述第二锁对象)。若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,说明该线程调度指令的待执行线程不存在连续加锁操作。
(2.1.3)若该线程调度指令的执行类型为解锁类型,将该线程调度指令的执行对象确定为第三锁对象,若所述第一集合中存在与所述第三锁对象一致的锁对象,删除所述第一集合中的与所述第三锁对象一致的锁对象,若所述第二集合中存在与所述第三锁对象一致的锁对象,删除所述第二集合中的与所述第三锁对象一致的锁对象。
例如,线程调度指令为T1{U(B)}5,该线程调度指令的执行类型为解锁类型(U),将该线程调度指令的执行对象(锁对象B)确定为第三锁对象。第一集合为{A,B},第二集合为{A,B},删除第一集合中的锁对象B,删除第二集合中的锁对象B。
(2.2)若该线程调度指令是该线程调度子序列的最后一个线程调度指令,清空所述第一集合和所述第二集合。
(C)组合所述多个线程调度子序列的一个或多个连续锁申请元素,得到所述锁申请序列。
103,从所述锁申请序列中查找所述被测试程序的锁环路数组。
在一具体实施例中,所述从所述锁申请序列中查找所述被测试程序的锁环路数组包括:
(A)创建锁环路栈、第三集合和锁对象变量,对所述锁申请序列中的每个连续锁申请元素设置读取标识符,所述读取标识符的初始值为0。
其中,所述读取标识符用以标识该连续锁申请元素是否被读取,0表示未被读取,1表示已被读取。
(B)从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第i个连续锁申请元素Ai为起点的所述锁环路数组,1≤i≤n,n为所述锁申请序列中的连续锁申请元素的数量:
(1)将Ai对所述锁环路栈进行入栈,将Ai的待执行线程加入所述第三集合,将Ai的读取标识符设置为1,将Ai的第一锁对象赋值给所述锁对象变量。
Ai的第一锁对象可以是Ai需要持有而实际没有持有的锁对象。
(2)若所述锁环路栈不为空,从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第j个连续锁申请元素Aj为结束点的所述锁环路数组,其中1≤j≤n:
(2.1)判断Aj的第二锁对象与所述锁对象变量的值是否一致且Aj的读取标识符是否为0。
(2.2)若Aj的第二锁对象与所述锁对象变量的值一致且Aj的读取标识符为0,将Aj对所述锁环路栈进行入栈,将Aj的待执行线程加入所述第三集合,将Aj的标识符设置为1,将Aj的第一锁对象赋值给所述锁对象变量。
Aj的第二锁对象与所述锁对象变量的值一致,表示Aj持有的锁对象与Ai需要持有的锁对象一致。Aj的第一锁对象可以是Aj需要持有而实际没有持有的锁对象。
(2.3)判断Aj的第一锁对象与Ai的第二锁对象是否一致且所述第三集合中的待执行线程是否一致。
(2.4)若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程不一致,确定所述锁环路栈中的连续锁申请元素为以Ai为起点以Aj为结束点的所述锁环路数组。
例如,锁环路栈中的两个连续锁申请元素分别为“T1-(A,B)-(1,2)-{A}”和“T1-(B,A)-(3,4)-{B}”。
在另一实施例中,所述方法还包括:
若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程一致,对所述锁环路栈中的Aj进行出栈,并将出栈后的所述锁环路栈中位于栈顶的连续锁申请元素的第一锁对象赋值给所述锁对象变量。
在另一实施例中,所述方法还包括:
若Aj的第二锁对象与所述锁对象变量的值不一致或Aj的读取标识符为0,则查找以Aj+1为结束点的所述锁环路数组。
在另一实施例中,所述方法还包括:
若所述锁环路栈为空,则将所述锁申请序列中的每个连续锁申请元素的读取标识符设置为0,初始化第三集合和锁对象变量,查找以Ai+1为起点的所述锁环路数组。
104,判断所述锁环路数组是否有效。
在一具体实施例中,所述判断所述锁环路数组是否有效包括:
若所述锁环路数组中待执行线程相同的连续锁申请元素之间不存在环路缺口,且所述锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路,则所述锁环路数组有效;
若所述锁环路数组中待执行线程相同的连续锁申请元素之间存在环路缺口,或所述锁环路数组中待执行线程不同的连续锁申请元素之间存在门锁环路,则所述锁环路数组无效。
例如,若锁环路数组中存在两个待执行线程相同的连续锁申请元素“T1-(A,B)-(1,2)-{A}”、“T1-(C,D)-(9,10)-{C}”,相同的待执行线程为T1,锁环路数组中的T1的最后一个连续锁申请元素的第一锁对象为锁对象D,锁环路数组中的T1的第一个连续锁申请元素的第二锁对象为锁对象A。当T1需要持有锁对象D时,若T1持有锁对象A,则锁环路数组中的待执行线程相同的连续锁申请元素不存在环路缺口。
例如,锁环路数组中任意两个待执行线程不同的连续锁申请元素之间不存在相同的第二锁对象,则锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路。多个不同线程在对锁对象进行加锁操作之前,都需要先持有同一个锁对象,将先持有的同一个锁对象称为门锁。
105,若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列。
在一具体实施例中,所述根据所述锁环路数组调整所述线程调度序列包括:
(1)将所述线程调度序列的线程调度指令的执行索引设置为1;
(2)若所述线程调度序列的给定线程调度指令的待执行线程与所述锁环路数组的给定连续锁申请元素的待执行线程一致、所述线程调度序列的给定线程调度指令的执行对象与所述锁环路数组的给定连续锁申请元素的第一锁对象一致且所述线程调度序列的给定线程调度指令的执行类型为加锁类型,则所述线程调度序列的给定线程调度指令与所述锁环路数组的给定连续锁申请元素一一对应,在所述线程调度序列中将所述给定线程调度指令的执行索引设置为-1;
(3)若所述线程调度序列中的除所述给定线程调度指令外的目标线程调度指令位于所述给定线程调度指令之后且待执行线程与所述给定线程调度指令的待执行线程一致,或若所述线程调度序列的目标线程调度指令之后不存在所述给定线程调度指令,则将所述目标线程调度指令的执行索引设置为0;
(4)删除执行索引为0的线程调度指令,将执行索引为0的线程调度指令移动至所述线程调度序列的尾部。
106,按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
根据所述锁环路数组调整所述线程调度序列得到的所述新线程调度序列是存在死锁的线程调度序列。按照所述新线程调度序列执行所述被测试程序,可以使程序发生死锁,验证了被测试程序存在潜在死锁的正确性。
实施例一检测程序中的潜在死锁,提升了检测潜在死锁的效率。
实施例二
图2是本发明实施例二提供的程序测试装置的结构图。所述程序测试装置20应用于计算机装置。本装置的程序测试是检测程序中的潜在死锁。如图2所示,所述程序测试装置20可以包括获取模块201、生成模块202、查找模块203、判断模块204、调整模块205、确认模块206。
获取模块201,用于获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引。
在一具体实施例中,所述获取被测试程序的线程调度序列包括:
根据所述被测试程序的线程和执行路径生成多个被测试子程序;
获取每个被测试子程序的线程调度子序列,得到多个线程调度子序列,每个线程调度子序列包括一个或多个依执行顺序组成的线程调度指令;
对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列。
例如,给定被测试程序存在二个线程(即两个主体代码),第一个线程存在两个执行路径“a-b”和“a-c”,第二个线程存在两个执行路径“d-e”和“d-f”,生成四个被测试子程序,四个被测试子程序的执行路径分别为:“a-b”、“a-c”、“d-e”和“d-f”;获取每个被测试子程序的线程调度子序列为:“T1{L(A)}1-T1{L(B)}2”、“T1{L(A)}1-T1{L(C)}2”、“T2{L(D)}1-T1{L(E)}2”、“T2{L(D)}1-T1{L(F)}2”,其中,T1、T2为待执行线程,“L()”为执行类型(表示lock,执行类型为加锁类型),A、B、C、D、E、F为执行对象,1和2为执行索引;对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列“T1{L(A)}1-T1{L(B)}2-T2{L(D)}3-T1{L(E)}4”、“T1{L(A)}1-T1{L(B)}2-T2{L(D)}3-T1{L(F)}4”、“T1{L(A)}1-T1{L(C)}2-T2{L(D)}3-T1{L(E)}4”或“T1{L(A)}1-T1{L(C)}2-T2{L(D)}3-T1{L(F)}4”。
在另一实施例中,所述获取每个被测试子程序的线程调度序列包括:
在该被测试子程序的可执行代码中插入监视代码;
执行该被测试子程序,使通过执行该子监视代码在该被测试子程序的内存空间记录线程调度指令;
依执行顺序存储线程调度指令,得到所述线程调度子序列。
生成模块202,用于根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成。
在一具体实施例中,所述根据所述线程调度序列生成锁申请序列包括:
(A)从所述线程调度序列中依所述执行索引的顺序读取每个执行线程的线程调度指令,将读取的每个执行线程的线程调度指令依次组合为每个执行线程的线程调度子序列。
例如,线程调度序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6-T2{L(G)}7-T2{L(A)}8-T2{L(B)}9-T2{U(B)}10-T2{U(A)}11-T2{U(G)}12”,其中“U()”为执行类型(表示unlock,执行类型为解锁类型),G为执行对象。分别读取执行线程为T1和T2的线程调度指令,将执行线程T1的线程调度指令依次组合为执行线程T1的线程调度子序列,将执行线程T2的线程调度指令依次组合为执行线程T2的线程调度子序列得到两个线程调度子序列,两个线程调度子序列分别为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,“T2{L(G)}7-T2{L(A)}8-T2{L(B)}9-T2{U(B)}10-T2{U(A)}11-T2{U(G)}12”。
(B)生成每个线程调度子序列的一个或多个连续锁申请元素。
在一具体实施例中,所述生成每个线程调度子序列的一个或多个连续锁申请元素包括:
(1)初始化第一集合和第二集合。
(2)从该线程调度子序列的第一个线程调度指令开始,对每一个线程调度指令执行以下步骤:
(2.1)判断该线程调度指令的执行类型。
(2.1.1)若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,将该线程调度指令的执行对象加入所述第一集合。
例如,线程调度子序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,第一集合和第二集合为空集,读取第一个线程调度指令“T1{L(A)}1”,该线程调度指令的执行类型为加锁类型(L)且第一集合中的锁对象的数量小于1,将锁对象A加入第一集合。
(2.1.2)若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,将该线程调度指令的执行对象作为第一锁对象,将所述第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象确定为第二锁对象,将所述第二锁对象加入所述第二集合,生成一个连续锁申请元素,该连续锁申请元素包括该线程调度指令的待执行线程、所述第二锁对象、所述第一锁对象、该线程调度指令的执行索引、所述第二锁对象所属的线程调度指令的执行索引和所述第二集合的锁对象。
例如,线程调度子序列为“T1{L(A)}1-T1{L(B)}2-T1{L(C)}3-T1{U(C)}4-T1{U(B)}5-T1{U(A)}6”,第一集合包括锁对象A,第二集合为空集,读取第二个线程调度指令“T1{L(B)}2”,该线程调度指令的执行类型为加锁类型(L)且第一集合中的锁对象的数量等于1,将B确定为第一锁对象,将第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象(锁对象A)确定为第二锁对象,其中锁对象A所属的线程调度指令(T1{L(A)}1)的执行索引为1,该线程调度指令(T1{L(B)}2)的执行索引为2。将第二锁对象(锁对象A)加入第二集合。生成的连续锁申请元素为“T1-(A,B)-(1,2)-{A}”,其中,T1为该线程调度指令的待执行线程,A为第二锁对象,B为第一锁对象,1为第二锁对象所属的线程调度指令的执行索引,2为该线程调度指令的执行索引,{A}为第二集合的锁对象。
若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,说明该线程调度指令的待执行线程至少存在一次连续加锁操作,因此将所述第二锁对象加入所述第二集合,表示该线程调度指令的待执行线程持有所述第二锁对象(即如果另一线程需要持有所述第二锁对象,需等待该线程调度指令的待执行线程解锁所述第二锁对象)。若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,说明该线程调度指令的待执行线程不存在连续加锁操作。
(2.1.3)若该线程调度指令的执行类型为解锁类型,将该线程调度指令的执行对象确定为第三锁对象,若所述第一集合中存在与所述第三锁对象一致的锁对象,删除所述第一集合中的与所述第三锁对象一致的锁对象,若所述第二集合中存在与所述第三锁对象一致的锁对象,删除所述第二集合中的与所述第三锁对象一致的锁对象。
例如,线程调度指令为T1{U(B)}5,该线程调度指令的执行类型为解锁类型(U),将该线程调度指令的执行对象(锁对象B)确定为第三锁对象。第一集合为{A,B},第二集合为{A,B},删除第一集合中的锁对象B,删除第二集合中的锁对象B。
(2.2)若该线程调度指令是该线程调度子序列的最后一个线程调度指令,清空所述第一集合和所述第二集合。
(C)组合所述多个线程调度子序列的一个或多个连续锁申请元素,得到所述锁申请序列。
查找模块203,用于从所述锁申请序列中查找所述被测试程序的锁环路数组。
在一具体实施例中,所述从所述锁申请序列中查找所述被测试程序的锁环路数组包括:
(A)创建锁环路栈、第三集合和锁对象变量,对所述锁申请序列中的每个连续锁申请元素设置读取标识符,所述读取标识符的初始值为0。
其中,所述读取标识符用以标识该连续锁申请元素是否被读取,0表示未被读取,1表示已被读取。
(B)从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第i个连续锁申请元素Ai为起点的所述锁环路数组,1≤i≤n,n为所述锁申请序列中的连续锁申请元素的数量:
(1)将Ai对所述锁环路栈进行入栈,将Ai的待执行线程加入所述第三集合,将Ai的读取标识符设置为1,将Ai的第一锁对象赋值给所述锁对象变量。
Ai的第一锁对象可以是Ai需要持有而实际没有持有的锁对象。
(2)若所述锁环路栈不为空,从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第j个连续锁申请元素Aj为结束点的所述锁环路数组,其中1≤j≤n:
(2.1)判断Aj的第二锁对象与所述锁对象变量的值是否一致且Aj的读取标识符是否为0。
(2.2)若Aj的第二锁对象与所述锁对象变量的值一致且Aj的读取标识符为0,将Aj对所述锁环路栈进行入栈,将Aj的待执行线程加入所述第三集合,将Aj的标识符设置为1,将Aj的第一锁对象赋值给所述锁对象变量。
Aj的第二锁对象与所述锁对象变量的值一致,表示Aj持有的锁对象与Ai需要持有的锁对象一致。Aj的第一锁对象可以是Aj需要持有而实际没有持有的锁对象。
(2.3)判断Aj的第一锁对象与Ai的第二锁对象是否一致且所述第三集合中的待执行线程是否一致。
(2.4)若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程不一致,确定所述锁环路栈中的连续锁申请元素为以Ai为起点以Aj为结束点的所述锁环路数组。
例如,锁环路栈中的两个连续锁申请元素分别为“T1-(A,B)-(1,2)-{A}”和“T1-(B,A)-(3,4)-{B}”。
在另一实施例中,所述方法还包括:
若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程一致,对所述锁环路栈中的Aj进行出栈,并将出栈后的所述锁环路栈中位于栈顶的连续锁申请元素的第一锁对象赋值给所述锁对象变量。
在另一实施例中,所述方法还包括:
若Aj的第二锁对象与所述锁对象变量的值不一致或Aj的读取标识符为0,则查找以Aj+1为结束点的所述锁环路数组。
在另一实施例中,所述方法还包括:
若所述锁环路栈为空,则将所述锁申请序列中的每个连续锁申请元素的读取标识符设置为0,初始化第三集合和锁对象变量,查找以Ai+1为起点的所述锁环路数组。
判断模块204,用于判断所述锁环路数组是否有效。
在一具体实施例中,所述判断所述锁环路数组是否有效包括:
若所述锁环路数组中待执行线程相同的连续锁申请元素之间不存在环路缺口,且所述锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路,则所述锁环路数组有效;
若所述锁环路数组中待执行线程相同的连续锁申请元素之间存在环路缺口,或所述锁环路数组中待执行线程不同的连续锁申请元素之间存在门锁环路,则所述锁环路数组无效。
例如,若锁环路数组中存在两个待执行线程相同的连续锁申请元素“T1-(A,B)-(1,2)-{A}”、“T1-(C,D)-(9,10)-{C}”,相同的待执行线程为T1,锁环路数组中的T1的最后一个连续锁申请元素的第一锁对象为锁对象D,锁环路数组中的T1的第一个连续锁申请元素的第二锁对象为锁对象A。当T1需要持有锁对象D时,若T1持有锁对象A,则锁环路数组中的待执行线程相同的连续锁申请元素不存在环路缺口。
例如,锁环路数组中任意两个待执行线程不同的连续锁申请元素之间不存在相同的第二锁对象,则锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路。多个不同线程在对锁对象进行加锁操作之前,都需要先持有同一个锁对象,将先持有的同一个锁对象称为门锁。
调整模块205,用于若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列。
在一具体实施例中,所述根据所述锁环路数组调整所述线程调度序列包括:
(1)将所述线程调度序列的线程调度指令的执行索引设置为1;
(2)若所述线程调度序列的给定线程调度指令的待执行线程与所述锁环路数组的给定连续锁申请元素的待执行线程一致、所述线程调度序列的给定线程调度指令的执行对象与所述锁环路数组的给定连续锁申请元素的第一锁对象一致且所述线程调度序列的给定线程调度指令的执行类型为加锁类型,则所述线程调度序列的给定线程调度指令与所述锁环路数组的给定连续锁申请元素一一对应,在所述线程调度序列中将所述给定线程调度指令的执行索引设置为-1;
(3)若所述线程调度序列中的除所述给定线程调度指令外的目标线程调度指令位于所述给定线程调度指令之后且待执行线程与所述给定线程调度指令的待执行线程一致,或若所述线程调度序列的目标线程调度指令之后不存在所述给定线程调度指令,则将所述目标线程调度指令的执行索引设置为0;
(4)删除执行索引为0的线程调度指令,将执行索引为0的线程调度指令移动至所述线程调度序列的尾部。
确认模块206,用于按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
根据所述锁环路数组调整所述线程调度序列得到的所述新线程调度序列是存在死锁的线程调度序列。按照所述新线程调度序列执行所述被测试程序,可以使程序发生死锁,验证了被测试程序存在潜在死锁的正确性。
实施例二的程序测试装置20用于检测程序中的潜在死锁,提升了检测潜在死锁的效率。
实施例三
本实施例提供一种计算机可读存储介质,该计算机可读存储介质上存储有计算机程序,该计算机程序被处理器执行时实现上述程序测试方法实施例中的步骤,例如图1所示的101-106:
101,获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
102,根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
103,从所述锁申请序列中查找所述被测试程序的锁环路数组;
104,判断所述锁环路数组是否有效;
105,若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
106,按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
或者,该计算机程序被处理器执行时实现上述装置实施例中各模块的功能,例如图2中的模块201-206:
获取模块201,用于获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
生成模块202,用于根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
查找模块203,用于从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断模块204,用于判断所述锁环路数组是否有效;
调整模块205,用于若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
确认模块206,用于按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
实施例四
图3为本发明实施例四提供的计算机装置的示意图。所述计算机装置30包括存储器301、处理器302以及存储在所述存储器301中并可在所述处理器302上运行的计算机程序303,例如程序测试程序。所述处理器302执行所述计算机程序303时实现上述程序测试方法实施例中的步骤,例如图1所示的101-106:
101,获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
102,根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
103,从所述锁申请序列中查找所述被测试程序的锁环路数组;
104,判断所述锁环路数组是否有效;
105,若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
106,按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
或者,该计算机程序被处理器执行时实现上述装置实施例中各模块的功能,例如图2中的模块201-206:
获取模块201,用于获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
生成模块202,用于根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
查找模块203,用于从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断模块204,用于判断所述锁环路数组是否有效;
调整模块205,用于若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
确认模块206,用于按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
示例性的,所述计算机程序303可以被分割成一个或多个模块,所述一个或者多个模块被存储在所述存储器301中,并由所述处理器302执行,以完成本方法。所述一个或多个模块可以是能够完成特定功能的一系列计算机程序指令段,该指令段用于描述所述计算机程序303在所述计算机装置30中的执行过程。例如,所述计算机程序303可以被分割成图2中的获取模块201、生成模块202、查找模块203、判断模块204、调整模块205、确认模块206,各模块具体功能参见实施例二。
所述计算机装置30可以是桌上型计算机、笔记本、掌上电脑及云端服务器等计算设备。本领域技术人员可以理解,所述示意图3仅仅是计算机装置30的示例,并不构成对计算机装置30的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件,例如所述计算机装置30还可以包括输入输出设备、网络接入设备、总线等。
所称处理器302可以是中央处理单元(Central Processing Unit,CPU),还可以是其他通用处理器、数字信号处理器(Digital Signal Processor,DSP)、专用集成电路(Application Specific Integrated Circuit,ASIC)、现场可编程门阵列(Field-Programmable Gate Array,FPGA)或者其他可编程逻辑器件、分立门或者晶体管逻辑器件、分立硬件组件等。通用处理器可以是微处理器或者该处理器302也可以是任何常规的处理器等,所述处理器302是所述计算机装置30的控制中心,利用各种接口和线路连接整个计算机装置30的各个部分。
所述存储器301可用于存储所述计算机程序303,所述处理器302通过运行或执行存储在所述存储器301内的计算机程序或模块,以及调用存储在存储器301内的数据,实现所述计算机装置30的各种功能。所述存储器301可主要包括存储程序区和存储数据区,其中,存储程序区可存储操作系统、至少一个功能所需的应用程序(比如声音播放功能、图像播放功能等)等;存储数据区可存储根据计算机装置30的使用所创建的数据等。此外,存储器301可以包括非易失性存储器,例如硬盘、内存、插接式硬盘,智能存储卡(Smart MediaCard,SMC),安全数字(Secure Digital,SD)卡,闪存卡(Flash Card)、至少一个磁盘存储器件、闪存器件、或其他非易失性固态存储器件。
所述计算机装置30集成的模块如果以软件功能模块的形式实现并作为独立的产品销售或使用时,可以存储在一个计算机可读存储介质中。基于这样的理解,本发明实现上述实施例方法中的全部或部分流程,也可以通过计算机程序来指令相关的硬件来完成,所述的计算机程序可存储于一计算机可读存储介质中,该计算机程序在被处理器执行时,可实现上述各个方法实施例的步骤。其中,所述计算机程序包括计算机程序代码,所述计算机程序代码可以为源代码形式、对象代码形式、可执行文件或某些中间形式等。所述计算机可读介质可以包括:能够携带所述计算机程序代码的任何实体或装置、记录介质、U盘、移动硬盘、磁碟、光盘、计算机存储器、只读存储器(ROM,Read-Only Memory)。
在本发明所提供的几个实施例中,应该理解到,所揭露的系统,装置和方法,可以通过其它的方式实现。例如,以上所描述的装置实施例仅仅是示意性的,例如,所述模块的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式。
所述作为分离部件说明的模块可以是或者也可以不是物理上分开的,作为模块显示的部件可以是或者也可以不是物理模块,即可以位于一个地方,或者也可以分布到多个网络单元上。可以根据实际的需要选择其中的部分或者全部模块来实现本实施例方案的目的。
另外,在本发明各个实施例中的各功能模块可以集成在一个处理模块中,也可以是各个模块单独物理存在,也可以两个或两个以上模块集成在一个模块中。上述集成的模块既可以采用硬件的形式实现,也可以采用硬件加软件功能模块的形式实现。
上述以软件功能模块的形式实现的集成的模块,可以存储在一个计算机可读存储介质中。上述软件功能模块存储在一个可读存储介质中,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)或处理器(processor)执行本发明各个实施例所述方法的部分步骤。
对于本领域技术人员而言,显然本发明不限于上述示范性实施例的细节,而且在不背离本发明的精神或基本特征的情况下,能够以其他的具体形式实现本发明。因此,无论从哪一点来看,均应将实施例看作是示范性的,而且是非限制性的,本发明的范围由所附权利要求而不是上述说明限定,因此旨在将落在权利要求的等同要件的含义和范围内的所有变化涵括在本发明内。不应将权利要求中的任何附关联图标记视为限制所涉及的权利要求。此外,显然“包括”一词不排除其他模块或步骤,单数不排除复数。系统权利要求中陈述的多个模块或装置也可以由一个模块或装置通过软件或者硬件来实现。第一,第二等词语用来表示名称,而并不表示任何特定的顺序。
最后应说明的是,以上实施例仅用以说明本发明的技术方案而非限制,尽管参照较佳实施例对本发明进行了详细说明,本领域的普通技术人员应当理解,可以对本发明的技术方案进行修改或等同替换,而不脱离本发明技术方案的精神和范围。
Claims (8)
1.一种程序测试方法,其特征在于,所述方法包括:
获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成,其中,所述根据所述线程调度序列生成锁申请序列包括:从所述线程调度序列中依所述执行索引的顺序读取每个执行线程的线程调度指令,将读取的每个执行线程的线程调度指令依次组合为每个执行线程的线程调度子序列;生成每个线程调度子序列的一个或多个连续锁申请元素;组合所述多个线程调度子序列的一个或多个连续锁申请元素,得到所述锁申请序列;其中,所述生成每个线程调度子序列的一个或多个连续锁申请元素包括:初始化第一集合和第二集合;从该线程调度子序列的第一个线程调度指令开始,对每一个线程调度指令执行以下步骤:判断该线程调度指令的执行类型;若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量小于1,将该线程调度指令的执行对象加入所述第一集合;若该线程调度指令的执行类型为加锁类型且所述第一集合中的锁对象的数量大于或等于1,将该线程调度指令的执行对象作为第一锁对象,将所述第一集合中执行索引距离该线程调度指令最近的线程调度指令的执行对象确定为第二锁对象,将所述第二锁对象加入所述第二集合,生成一个连续锁申请元素,该连续锁申请元素包括该线程调度指令的待执行线程、所述第二锁对象、所述第一锁对象、该线程调度指令的执行索引、所述第二锁对象所属的线程调度指令的执行索引和所述第二集合的锁对象;
从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断所述锁环路数组是否有效,包括:若所述锁环路数组中待执行线程相同的连续锁申请元素之间不存在环路缺口,且所述锁环路数组中待执行线程不同的连续锁申请元素之间不存在门锁环路,则所述锁环路数组有效;若所述锁环路数组中待执行线程相同的连续锁申请元素之间存在环路缺口,或所述锁环路数组中待执行线程不同的连续锁申请元素之间存在门锁环路,则所述锁环路数组无效;
若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
2.如权利要求1所述的方法,其特征在于,所述获取被测试程序的线程调度序列包括:
根据所述被测试程序的线程和执行路径生成多个被测试子程序;
获取每个被测试子程序的线程调度子序列,得到多个线程调度子序列,每个线程调度子序列包括一个或多个依执行顺序组成的线程调度指令;
对不同待执行线程的所述多个线程调度子序列进行排列组合,得到所述被测试程序的线程调度序列。
3.如权利要求1所述的方法,其特征在于,所述方法还包括:
若该线程调度指令的执行类型为解锁类型,将该线程调度指令的执行对象确定为第三锁对象,若所述第一集合中存在与所述第三锁对象一致的锁对象,删除所述第一集合中的与所述第三锁对象一致的锁对象,若所述第二集合中存在与所述第三锁对象一致的锁对象,删除所述第二集合中的与所述第三锁对象一致的锁对象;
若该线程调度指令是该线程调度子序列的最后一个线程调度指令,清空所述第一集合和所述第二集合。
4.如权利要求1所述的方法,其特征在于,所述从所述锁申请序列中查找所述被测试程序的锁环路数组包括:
创建锁环路栈、第三集合和锁对象变量,对所述锁申请序列中的每个连续锁申请元素设置读取标识符,所述读取标识符的初始值为0;
从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第i个连续锁申请元素Ai为起点的所述锁环路数组,1≤i≤n,n为所述锁申请序列中的连续锁申请元素的数量:
将Ai对所述锁环路栈进行入栈,将Ai的待执行线程加入所述第三集合,将Ai的读取标识符设置为1,将Ai的第一锁对象赋值给所述锁对象变量;
若所述锁环路栈不为空,从所述锁申请序列中的第一个连续锁申请元素开始,逐个查找以第j个连续锁申请元素Aj为结束点的所述锁环路数组,其中1≤j≤n:
判断Aj的第二锁对象与所述锁对象变量的值是否一致且Aj的读取标识符是否为0;
若Aj的第二锁对象与所述锁对象变量的值一致且Aj的读取标识符为0,将Aj对所述锁环路栈进行入栈,将Aj的待执行线程加入所述第三集合,将Aj的标识符设置为1,将Aj的第一锁对象赋值给所述锁对象变量;
判断Aj的第一锁对象与Ai的第二锁对象是否一致且所述第三集合中的待执行线程是否一致;
若Aj的第一锁对象与Ai的第二锁对象一致且所述第三集合中的待执行线程不一致,确定所述锁环路栈中的连续锁申请元素为以Ai为起点以Aj为结束点的所述锁环路数组。
5.如权利要求1所述的方法,其特征在于,所述根据所述锁环路数组调整所述线程调度序列包括:
将所述线程调度序列的线程调度指令的执行索引设置为1;
若所述线程调度序列的给定线程调度指令的待执行线程与所述锁环路数组的给定连续锁申请元素的待执行线程一致、所述线程调度序列的给定线程调度指令的执行对象与所述锁环路数组的给定连续锁申请元素的第一锁对象一致且所述线程调度序列的给定线程调度指令的执行类型为加锁类型,则所述线程调度序列的给定线程调度指令与所述锁环路数组的给定连续锁申请元素一一对应,在所述线程调度序列中将所述给定线程调度指令的执行索引设置为-1;
若所述线程调度序列中的除所述给定线程调度指令外的目标线程调度指令位于所述给定线程调度指令之后且待执行线程与所述给定线程调度指令的待执行线程一致,或若所述线程调度序列的目标线程调度指令之后不存在所述给定线程调度指令,则将所述目标线程调度指令的执行索引设置为0;
删除执行索引为0的线程调度指令,将执行索引为0的线程调度指令移动至所述线程调度序列的尾部。
6.一种程序测试装置,其特征在于,所述装置包括用于实现如权利要求1至5中任意一项所述的方法的模块,所述装置包括:
获取模块,用于获取被测试程序的线程调度序列,所述线程调度序列由多个线程调度指令依执行顺序组成,线程调度指令包括待执行线程、执行类型、执行对象和执行索引;
生成模块,用于根据所述线程调度序列生成锁申请序列,所述锁申请序列由连续锁申请元素组成;
查找模块,用于从所述锁申请序列中查找所述被测试程序的锁环路数组;
判断模块,用于判断所述锁环路数组是否有效;
调整模块,用于若所述锁环路数组有效,根据所述锁环路数组调整所述线程调度序列,得到新线程调度序列;
确认模块,用于按照所述新线程调度序列执行所述被测试程序,若所述被测试程序发生死锁,确认所述被测试程序存在潜在死锁。
7.一种计算机装置,其特征在于,所述计算机装置包括处理器,所述处理器用于执行存储器中存储的计算机程序以实现如权利要求1-5中任一项所述程序测试方法。
8.一种计算机可读存储介质,所述计算机可读存储介质上存储有计算机程序,其特征在于,所述计算机程序被处理器执行时实现如权利要求1-5中任一项所述程序测试方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202010158772.3A CN111522730B (zh) | 2020-03-09 | 2020-03-09 | 程序测试方法及装置、计算机装置、计算机可读介质 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202010158772.3A CN111522730B (zh) | 2020-03-09 | 2020-03-09 | 程序测试方法及装置、计算机装置、计算机可读介质 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN111522730A CN111522730A (zh) | 2020-08-11 |
CN111522730B true CN111522730B (zh) | 2024-03-29 |
Family
ID=71901482
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202010158772.3A Active CN111522730B (zh) | 2020-03-09 | 2020-03-09 | 程序测试方法及装置、计算机装置、计算机可读介质 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN111522730B (zh) |
Families Citing this family (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN113225269B (zh) * | 2021-04-16 | 2022-11-22 | 鹏城实验室 | 基于容器的工作流调度方法、装置、系统及存储介质 |
CN115344360A (zh) * | 2021-05-13 | 2022-11-15 | 华为技术有限公司 | 死锁检测方法、装置以及相关设备 |
Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CA2472887A1 (en) * | 2003-06-30 | 2004-12-30 | Gravic, Inc. | Methods for ensuring referential integrity in multithreaded replication engines |
WO2010139260A1 (zh) * | 2009-06-04 | 2010-12-09 | 中兴通讯股份有限公司 | 数据库事务锁机制的死锁检测方法及装置 |
CN102073589A (zh) * | 2010-12-29 | 2011-05-25 | 北京邮电大学 | 一种基于代码静态分析的数据竞争检测方法及系统 |
CN109669858A (zh) * | 2018-11-22 | 2019-04-23 | 新华三技术有限公司合肥分公司 | 程序死锁的测试方法、装置和设备 |
-
2020
- 2020-03-09 CN CN202010158772.3A patent/CN111522730B/zh active Active
Patent Citations (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CA2472887A1 (en) * | 2003-06-30 | 2004-12-30 | Gravic, Inc. | Methods for ensuring referential integrity in multithreaded replication engines |
WO2010139260A1 (zh) * | 2009-06-04 | 2010-12-09 | 中兴通讯股份有限公司 | 数据库事务锁机制的死锁检测方法及装置 |
CN102073589A (zh) * | 2010-12-29 | 2011-05-25 | 北京邮电大学 | 一种基于代码静态分析的数据竞争检测方法及系统 |
CN109669858A (zh) * | 2018-11-22 | 2019-04-23 | 新华三技术有限公司合肥分公司 | 程序死锁的测试方法、装置和设备 |
Also Published As
Publication number | Publication date |
---|---|
CN111522730A (zh) | 2020-08-11 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Černý et al. | Quantitative synthesis for concurrent programs | |
TWI442233B (zh) | 使用交易以平行化循序框架之方法及用於記錄相關指令之電腦儲存媒體 | |
US6285974B1 (en) | Hardware verification tool for multiprocessors | |
US8060880B2 (en) | System using backward inter-procedural analysis for determining alternative coarser grained lock when finer grained locks exceeding threshold | |
Bala et al. | Efficient instruction scheduling using finite state automata | |
TWI451340B (zh) | 使用交易以平行化循序框架之方法及電腦可讀取媒體 | |
US20080209436A1 (en) | Automated testing of programs using race-detection and flipping | |
Park et al. | BLoG: Post-silicon bug localization in processors using bug localization graphs | |
US8055492B2 (en) | Non-unique results in design verification by test programs | |
KR20090082256A (ko) | Stm 시스템에서 트랜잭션들에 순서화를 적용하는 방법, 순서화에 의한 경쟁 관리를 제공하는 방법 및 컴퓨터 판독가능 매체 | |
JP2010134614A (ja) | 並列化処理方法、システム、及びプログラム | |
TW200901026A (en) | Exception ordering in contention management to support speculative sequential semantics | |
CN111522730B (zh) | 程序测试方法及装置、计算机装置、计算机可读介质 | |
KR102013582B1 (ko) | 혼합 모드 프로그램의 소스 코드 오류 위치 검출 장치 및 방법 | |
WO2008043005A1 (en) | Model checking parameterized threads for safety | |
US8392891B2 (en) | Technique for finding relaxed memory model vulnerabilities | |
Bucci et al. | Correctness verification and performance analysis of real-time systems using stochastic preemptive time Petri nets | |
Daly | Creating a virtuous cycle in performance testing at MongoDB | |
Qiu et al. | Scalable fsm parallelization via path fusion and higher-order speculation | |
US8789060B1 (en) | Deterministic, parallel execution with overlapping regions | |
EP2913758A1 (en) | Loop abstraction for model checking | |
CN110706108B (zh) | 在区块链中并发执行交易的方法和装置 | |
CN108459963B (zh) | 一种基于中断控制流图的中断验证方法 | |
CN108469987B (zh) | 一种基于中断控制流图的中断验证系统 | |
Bowie | Applications of graph theory in computer systems |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |