无锁参考计数的制作方法

文档序号:18902206发布日期:2019-10-18 22:05阅读:186来源:国知局
无锁参考计数的制作方法

本发明要求于2017年3月10日递交的发明名称为“无锁参考计数”的第15/456,140号美国非临时专利申请案的在先申请优先权,该在先申请的内容以引入的方式并入本文。

本发明涉及使用参考计数器进行存储器管理的技术。



背景技术:

存储器管理系统通常跟踪创建后的存储器对象,并删除不再需要的那些对象,以使所使用的存储器再次变为可用。这种系统也称为垃圾收集器,其通常的工作是维护与每个存储器对象关联的引用计数。例如,引用计数用于跟踪存储器中正在创建或分配的对象,随后删除这些对象。当线程(或进程或其它实体)访问或以其它方式引用该存储器对象时,引用计数会增加。当所述线程对所述存储器对象删除引用时,所述引用计数会减少。当所述引用计数达到零时,假设所述存储器对象不再使用,所述存储器管理器可以释放所述存储器以进行重复使用,从而降低存储器耗尽的可能性。

此外,计算系统通常有多个处理器,通过在这些处理器上分配给定的工作负载可以提高计算吞吐量。每个处理器可以具有关联存储器,其运行速度高于主存储器。当多个线程在不同的处理器上执行并访问或共享通用存储器对象时,通常需要将该对象的引用计数从一个存储器传输到另一个存储器,这可能会导致延迟增加和处理效率降低。随着计算系统的规模不断扩大,并行执行的线程数量大幅增加,所述存储器管理可能会导致发布的参考计数指令数量增加,同时系统整体性能也会下降。



技术实现要素:

在第一实施例中,提供一种计算机实现的参考计数方法,包括:创建与父线程引用的对象对应的父线程计数器,所述父线程计数器包括分层计数器数据结构;创建子线程的子线程计数器,所述子线程计数器包括所述分层计数器数据结构,并将对所述对象的所述引用从所述父线程传递到所述子线程;更新所述父线程计数器中的所述分层计数器数据结构以引用所述子线程计数器,并更新所述子线程计数器中的所述分层计数器数据结构以指向所述父线程计数器;当所述子线程完成处理时通知所述父线程计数器。

在根据前述任一实施例的第二实施例中,创建所述父线程计数器包括:创建所述父线程计数器包括初始化所述分层计数器数据结构,以将父计数值设置为初始值1,将所述父线程的状态设置为活动,将子项列表设置为空,并将指针设置为空;创建所述子线程计数器包括初始化所述分层计数器数据结构,以将子计数值设置为初始值1,将所述父线程的状态设置为活动,将子项列表设置为空,并将指针设置为指向所述父线程计数器。

在根据前述任一实施例的第三实施例中,更新所述分层计数器数据结构包括:当所述父线程添加对所述对象的引用时,增加所述父线程计数器的所述父计数值;当父线程删除对所述对象的所述引用时,减少所述父线程计数器的所述父计数值;当所述子线程添加对所述对象的引用时,增加所述子引用计数器的所述子计数值;当所述子线程删除对所述对象的所述引用时,减少所述子引用计数器的所述子计数值。

在根据前述任一实施例的第四实施例中,所述计算机实现的方法还包括:完成处理后,将所述父线程和所述子线程的所述状态从活动改变为非活动;独立修改所述父线程和所述子线程中的子项列表,以添加或删除子计数器;将用于新添加子项的所述指针设置为指向直接父计数器。

在根据前述任一实施例的第五实施例中,删除对所述对象的所述引用包括:根据所述子线程计数值确定所述子线程计数器是否已完成处理;检查所述子线程计数器是否有所述子项列表;为响应所述子线程计数器的所述子计数值为零、所述子线程计数器的所述子线程列表为空或所述子项列表中列出的所述子线程全部为非活动以及所述子线程的所述状态为非活动,删除对所述对象的所述引用。

在根据前述任一实施例的第六实施例中,所述计算机实现的方法还包括:根据所述父计数值确定所述父线程计数器是否已完成处理;检查所述父线程中的所述指针;释放所述存储器中的所述对象,以响应所述指针为空和所述父线程的所述状态为非活动。

在根据前述任一实施例的第七实施例中,所述分层计数器数据结构包括计算对所述对象的所述引用数量的计数值,指示所述对象的状态为活动或非活动的变量、子计数器列表以及指向父计数器的指针。

在根据前述任一实施例的第八实施例中,指示对所述对象的所述引用数量的所述计数值由所述父线程和所述子线程中的一个独立修改;所述状态从活动状态改变为非活动状态;所述子计数器列表为所述线程中对应的一个线程标识各个子计数器;在初始创建所述线程计数器中的一个时设置所述指针。

在根据上述任一实施例的第九实施例中,所述父线程计数器和所述子线程计数器采用无锁参考计数。

在第十实施例中,提供一种用于参考计数的设备,包括:非瞬时性存储器,包括指令;一个或多个处理器,与所述存储器通信,其中所述一个或多个处理器执行所述指令完成以下操作,包括:创建与父线程引用的对象对应的父线程计数器,所述父线程计数器包括分层计数器数据结构;创建子线程的子线程计数器,所述子线程计数器包括所述分层计数器数据结构,并将对所述对象的所述引用从所述父线程传递到所述子线程;无锁定更新所述父线程计数器中的所述分层计数器数据结构以引用所述子线程计数器,并更新所述子线程计数器中的所述分层计数器数据结构以指向所述父线程计数器;当所述子线程完成处理时通知所述父线程计数器。

在第十一实施例中,提供一种非瞬时性计算机可读介质,存储用于参考计数的计算机指令,当一个或多个处理器执行所述计算机指令时,执行以下步骤:创建与父线程引用的对象对应的父线程计数器,所述父线程计数器包括分层计数器数据结构;创建子线程的子线程计数器,所述子线程计数器包括所述分层计数器数据结构,并将对所述对象的所述引用从所述父线程传递到所述子线程;更新所述父线程计数器中的所述分层计数器数据结构以引用所述子线程计数器,并更新所述子线程计数器中的所述分层计数器数据结构以指向所述父线程计数器;当所述子线程完成处理时通知所述父线程计数器。

提供本发明内容是为了以简化的形式引入概念的选择,这些概念将在以下具体实施方式中进行进一步的描述。本发明内容的目的不在于识别权利要求书保护的主题的关键特征或必要特征,也不在于帮助确定权利要求书保护的主题的范围。权利要求书保护的主题不限于用于解决在背景技术中提到的任何或全部缺点的实现方式。

附图说明

本发明的方面通过举例的方式示出但不受附图的限制,附图中相同的附图标记表示元件。

图1示出了根据一个实施例的分布式数据系统的示例;

图2a和图2b示出了按照传统方法引用存储器管理系统中的数据的线程示例;

图3a示出了引用存储在存储器中的数据的进程的两个线程的示例概述;

图3b示出了根据图3a的计数器的分层计数器数据结构;

图3c示出了实现图3b的分层计数器数据结构的示例调用流程;

图3d示出了多线程进程的示例,其中将父线程和子线程参考数据分配到存储器中;

图4a–4b示出了根据图1和图3a–3d中公开的实施例的参考计数流程图;

图5示出了根据图3a–3b、图3d和图4a–4b的本地线程计数器的流程图的一个实施例;

图6示出了可用于实现各种实施例的网络系统的框图。

具体实施方式

本发明涉及使用参考计数器进行存储器管理的技术。

存储器管理长期一直使用参考计数器跟踪引用存储器中存储的(指向)数据(对象)的线程数量。如上所述,随着计算系统中的线程数量增加,所述存储器管理可能导致发布的参考计数指令数量增加(开销增加),同时系统整体性能降低。

为了确保被一个线程引用的对象不同时被另一个线程访问,通常会引入锁定机制(例如,信号量)以防止访问被引用的对象。当引用对象时,所述锁定机制由来自所述系统的指令实现。随着每条指令锁定引用的对象,所述系统就会引入额外的开销。

在一个实施例中,为了减少指令总数并提高系统性能,引入了父线程计数器和子线程计数器。所述线程计数器中的每个线程计数器与一个或多个线程关联,并跟踪所述关联的线程对所述对象进行的引用数量。此外,所述线程计数器的每个线程计数器均包括分层计数器数据结构,所述分层计数器数据结构使用成员元素监控特定线程的整体状态,以促使所述计数器更新。

在一个实施例中,所述线程计数器无需锁定即可实现。也就是说,更新所述线程计数器的所述分层计数器数据结构的值不需要锁定所述线程计数器,便可以进行更新。

应理解的是,本发明的现有实施例可以以许多不同的形式实现,并且权利要求范围不应理解为仅限于本文所述的实施例。相反,提供这些实施例是为了使本发明内容更加透彻和完整,并将本发明实施例的概念完整地传达给本领域技术人员。事实上,本发明旨在覆盖这些实施例的替代方案、修改和等同方案,其包括在由所附权利要求书定义的本发明的范围和精神内。另外,在以下本发明实施例的详细描述中,阐述了许多特定细节以便提供透彻理解。但是,本领域普通技术人员清楚的是,本发明实施例可以在没有这些具体细节的情况下实施。

各种处理语言(如python)提供自动参考计数,即垃圾收集,其中存储器不再使用时自动释放。在这些类型的语言中,垃圾收集的一般方法是所述系统定期检查所有对象,以确定线程或进程是否仍在引用每个对象。如果仍在引用某个对象,则该对象保持不变。另一方面,如果不再引用该对象(例如,当前没有线程引用该对象),则所述系统将释放该对象。这种周期性检查行为会在不可预测的时间间隔内引入大量系统开销,因此不是理想的方案,尤其是在性能敏感的环境中。

其它处理语言例如c和c++,通常不提供自动垃圾收集,但提供手动机制来引用计数。在这些环境中,从所述存储器中释放对象由编程器显式管理。参考计数提供相对简单的垃圾收集机制,具有恒定的增量开销。根据这种参考计数机制,使用某种类型的指示器(例如,计数器)来确定是否正在处理对象。在引用对象时,所述指示器会通知所述系统正在处理对象,不应释放该对象,而不是引用该对象,则会通知所述系统不再处理所述对象,并可以释放该对象。

图1示出了根据一个实施例的分布式数据系统的示例。所述分布式数据系统100包括,例如,客户端设备(或节点)102a–102n、服务器104、应用服务器106a–106n、分布式数据存储器110和存储器管理器112。在一个实施例中,所述分布式数据系统是存储器管理系统。

客户端102a–102n可以是但不限于桌面个人计算机、笔记本电脑、pda、平板电脑、智能手机、销售点终端等可执行客户端应用(如网络浏览器)的设备。

所述服务器104可以包括一个或多个服务器,例如企业服务器(例如,web服务器),它们通过网络(未示出)向所述客户端102a–102n提供内容。所述网络可以是有线网络、无线网络或其组合,并且可以包括lan、wan、互联网或其组合。一种或多种网络协议中的任何一种都可以在所述网络中使用,例如tcp/ip。

应用服务器106a–106n(促进创建web应用和执行所述web应用的环境)可以分别包括进程(或应用)108a–108n1和本地存储器108b–108n2。在一个示例中,所述进程108a–108n1可以由所述客户端102a–102n使用,以将逻辑应用于分别存储在本地存储器108b–108n2中的分布式数据。进程108a–108n1可以包含一个或多个线程109。

线程109(或代码模块)在应用服务器106a–106n的多个核上执行,并且可以用于在访问存储器中的对象111时输入事务。在所述事务期间,所述线程109可以执行与所述对象111关联的所述引用计数110b的访问。

例如,所述本地存储器108b可以包括数据的本地实例或所述应用服务器106a-106n维护的所述分布式数据的对象,例如,由所述应用服务器106a-106n的本地客户端使用,或由应用服务器106a-106n中执行的进程108a-108n1使用。

分布式数据存储110包括,例如,数据结构110a、参考计数110b和锁110c。所述分布式数据存储器110可以存储包括分布式数据110a中的一个或多个数据,其中分布式数据110a可以包括所述应用服务器106a-106n可访问的所述分布式数据的实例。在一个实施例中,所述分布式数据110a可以分布在一个或多个计算机可访问介质上的分布式数据系统上。在另一实施例中,分布式数据存储器110可包括还托管应用服务器106a-106n中的一个或多个应用服务器的一个或多个计算机系统上的存储器。

在一个实施例中,所述进程108a–108n1可以向企业服务器104提供数据和/或服务,例如,由客户端102a–102n使用。所述应用服务器106a-106n可以向分布式数据存储器110发送分布式数据的更新以响应事件,例如修改本地存储器108a-108n中的本地数据的一个或多个属性,和/或作为常规维护将所述分布式数据与所述本地数据同步。在一个实施例中,属性可以是所述分布式数据的一部分或元素,并且可以是进程中可以使用的各种数据类型中的一种,例如编程语言对象或类(例如,java对象或类)、字符串、整数、布尔值、字符、实数表示或任何其它类型的计算机可表示数据。

分布式数据存储器110还可以包括锁110c,其中所述锁110c可以授予或拒绝对所述分布式数据110a的一个或多个部分的进程108a-108n1的访问。因此,当所述进程108a-108n1中的一个进程锁定所述分布式数据110a的一个或多个部分时,其它进程108a-108n1可能无法访问该部分。但是,同时,其它进程108a-108n1可锁定所述分布式数据110a的其它部分。

在一个实施例中,进程106a-106n可以持有一个或多个锁,其中每个锁110c对应于分布式数据110a的一个或多个部分。多线程进程106a-106n的线程109可以为所述分布式数据110a的一部分请求锁110c进行所述处理。在一个实施例中,所述锁110c通过锁定机制(未示出)实现,该锁定机制可以将所述锁授予所述线程进行处理。

在一个实施例中,为了访问分布式数据110a,应用服务器104中执行的进程108a–108n1中的一个进程可以为分布式数据110a的一部分请求锁110c,例如互斥锁。如果所述进程108a–108n1中的另一个进程当前未对分布式数据110a中的相同部分保留所述锁110c,则可以向所述请求的进程108a或108n1发放所述锁110c。如果另一进程为分布式数据110a的请求部分保留所述锁110c,则所述请求进程108a或108n1可进入等待状态,或者可在等待释放所述锁110c时继续执行另一任务。

存储器管理器112用于跟踪存储器中创建后的对象和删除不再需要的那些对象,以便释放所述存储器进行重新分配。这可以通过维护存储器中分配的每个对象的参考计数来实现。当线程(代码模块、进程或其它实体)访问或以其它方式引用该存储器对象时,引用计数会增加。当所述线程不再引用存储器中的对象时,所述引用计数会减少。当所述引用计数达到零或某个阈值时,所述存储器对象可以假定为不再使用,所述存储器管理器可以删除该对象并释放与该对象关联的存储器。

应理解的是,上述锁定和保护机制是非限制性示例,并且可以使用任何已知的锁定技术。

图2a和图2b示出了按照传统方法引用存储器管理系统中的数据的线程示例。特别地,图2a描述了引用存储在内存管理系统212的内存中的数据的进程的两个线程的概述。每个线程(主线程202和第一线程206)都有变量,这些变量引用(或指向)分配给内存中特定空间的数据,并且哪个引用计数器(rc)204跟踪正在进行的引用的数量。从线程变量到存储在存储器中的数据(以及所述关联的参考计数器204)的引用用黑箭头表示。

在一个实施例中,所述数据是对象abc(.1.),由主线程202和第一线程206共用。在另一实施例中,分配给存储器的所述对象abc(.1.)提供了使用所述参考计数器204维护参考计数(计数值)的功能。如所述示例所示,如果所述进程中超过一个线程202和206引用所述对象(例如,所述相同或共用对象)abc(.1.),它通常称为多线程进程。应理解的是,为简化讨论,只描述一进程的两个线程、一个对象和关联的参考计数器。但是,可以使用任何数量的进程、线程、对象和/或参考计数器。

为了确保所述参考计数器204在线程202和206访问期间正确更新,可以使用锁定机制在计数器更新期间(即所述计数值的增加或减少)保护所述参考计数器204。当多线程进程的线程202和206请求访问同一(共用)对象abc(.1.)时,实现使用锁(例如,信号量)的锁定机制尤其有用。

在此类带有锁定机制的实施例中,访问所述对象abc(.1.)的线程提供锁定指令,该指令通知其它线程(线程202和206之外的线程)对象abc(.1.)正在使用中,不应访问。某些类型的锁允许共用对象abc(.1.)同时由许多进程共用(例如,共享锁),而其它类型的锁可防止在同一对象abc(.1.)上授予任何类型的锁。应理解的是,可以使用任何已知的锁定时间,并且本发明不限于所述锁定机制。

如果没有锁定机制,则当另一个线程206已处理所述对象abc(.1.)时,所述参考计数器204可由一个线程202更新。在一个示例中,未能实现锁定会导致引用计数器204更新,其中发生所述引用对象abc(.1.)从存储器中提前释放,而线程仍在处理所述对象abc(.1.)。在另一示例中,所述引用对象abc(.1.)在线程完成对象abc(.1.)的处理后,不能从存储器中释放。在前一种情况下,数据处理可能不会在所述对象abc(.1.)释放之前完成;而在后一种情况下,所述对象abc(.1.)继续利用存储器空间,即使数据处理已完成。因此,应用所述锁定机制至关重要,以确保成功处理。

图2b示出了一个多线程进程的示例,其中主线程202和第一线程206引用数据(例如,对象abc(.1.))分配到存储器中。线程对所述对象的每个引用都会导致所述引用计数器204更新(例如,增加或减少)。例如,当主线程202引用所述对象abc(.1.),所述对象abc(.1.)从存储器访问,处理实体(例如应用服务器106a或106n(图1)在所述对象abc(.1.)上运行。为防止其它线程同时访问同一对象abc(.1.),可以使用上述锁定机制。

在示例中,主线程202包括变量(variable,简称var)“a”、“b”和“c”,其中每个变量都引用(指向)所述对象abc(.1.)。作为变量引用所述对象abc(.1.),所述参考计数器204增加(increased,简称inc)。由于变量超出范围(例如,所述变量是隐式或显式取消分配,或者在后续执行中不再被任何其它变量引用),引用计数器204会减少(decreased,简称dec)。

主线程202首先引用具有变量“a”的对象abc(.1.)。由于主线程202的引用,所述引用计数器204从初始零值增加到计数值“1”。然后,所述主线程202在210处将所述变量“a”传递到所述函数runtask{(foo(a)}中,该函数启动第一线程206。所述从第一线程206到具有变量“aa”的对象abc(.1.)的引用会导致所述引用计数器204将所述引用计数增加到计数值“2”。

在此阶段,将执行多个线程(即,主线程202和第一线程206)以及对所述对象abc(.1.)的任何引用更新所述对象abc(.1.)的参考计数器204。例如,所述主线程202的变量“b”和“c”对所述对象abc(.1.)的引用分别使所述参考计数器204增加到计数值“4”和“6”。当变量“b”和“c”完全对所述对象abc(.1.)的访问时,每个变量超出范围(“//b失效”和“//c失效”),因此不再可用。这将导致每个变量不再引用所述对象abc(.1.),从而将所述引用计数器204的计数值(在每个实例中)减至计数值“5”。在一个实施例中,变量“a”引用新对象abc(.20.)时,与所述对象abc(.1.)关联的参考计数器204从引用所述对象abc(.1.)超出范围(“//a已重新定义”)开始减少。

同样,第一线程206包括访问所述对象abc(.1.)的变量(variable,简称var)“aa”、“bb”、“cc”、“dd”、“x”、“y”、“z”和“u”。作为变量引用所述对象abc(.1.),所述参考计数器204增加。当变量超出范围时,所述参考计数器204会减少。例如,当变量“dd”引用所述对象abc(.1.)时,所述参考计数器204增加到计数值6,而当变量“bb”超出范围时,所述参考计数204从变量“bb”超出范围(“//bb失效”)开始减少。在此示例中,当最后一个变量“u”超出范围时,所述引用计数器204的计数值将减至零值,所述对象abc(.1.)被释放。

图3a和图3d示出了根据本发明实施例的引用存储器管理系统中的数据的线程示例。图3c和图3b是根据图3a和图3d的分层计数器数据结构和调用流程示例。

虽然在存储器中引用数据的常规方法有许多优点,但每次引用存储在存储器中的对象时,所述系统都会使用锁指令。随着对所述对象的引用数量增加,也会产生大量开销。也就是说,随着所述引用数量的增加,与所述引用关联的锁定指令数量也会增加。

图3a示出了引用存储在存储器中的数据的进程的两个线程的示例概述。进程的父线程302和子线程306类似于图2a的实施例,具有变量(variable,简称var),该变量引用(或指向)分配给存储器中特定空间的数据,并且引用计数器为特定空间跟踪所进行的引用的数量。但是,与传统方法不同,图3a的存储器管理系统312采用两个参考计数器rcpt302a和rccd308,其中每个参考计数器包括分层计数器数据结构,如下所述。

在所述存储器管理系统312的一个实施例中,当所述对象abc(.1.)分配给存储器时创建父线程计数器rcpt302a。所述父线程计数器rcpt302a使用分层计数器数据结构(参考图3b讨论)跟踪从父线程302到所述对象abc(.1.)的引用,该分层计数器数据结构跟踪(1)所述线程中从父线程302对所述对象abc(.1.)进行的引用数量(在该示例中,4个变量进行引用),(2)父线程302作为活动或非活动(即正在处理或完成处理)的状态,(3)子计数器列表(在该示例中,到子线程计数器306a)和(4)指向任何父线程的指针(在该示例中,所述父线程是所述根线程并且保持null或空值)。

当父线程302将(分支)304对所述对象abc(.1.)的引用传递到子线程306时,创建子线程计数器rccd308。与所述父线程计数器rcpt302a类似,所述子线程计数器rccd306a使用分层计数器数据结构跟踪从子线程306到所述对象abc(.1.)的引用。例如,所述子线程306的引用数量为两个(因为两个变量引用所述对象,如两个黑箭头所示),子线程306的状态为活动或非活动,子线程计数器列表因不存在所述子线程计数器306a的子项而为空,并且所述指针指回所述父线程计数器302a(因为父线程206传递了对所述对象的引用)。

因此,所述父线程计数器rcpt302a跟踪线程的发起(第一个引用)和线程的退出(超出范围或最后一个引用)。在一个实施例中,与图2a的实施例不同,对所述参考计数器rcpt302a和rccd308所做的引用(用黑箭头表示)不采用上述锁定机制。相反,所述参考计数器rcpt302a和rccd308以无锁方式(即,无锁定)运行。

在一个实施例中,所述父线程302和所述子线程306分别发起父线程计数器rcpt302a和子线程计数器rccd306a,所述子线程计数器rccd306a假设所述对象abc(.1.)的参考计数操作。例如,当所述父线程302或子线程306引用所述对象abc(.1.)时,不同于全局参考计数器rcg304,所述关联的线程计数器rcpt302a和rccd306a进行更新(例如,更新或修改所述分层计数器数据结构的一个或多个元素)。

在一个实施例中,所述父线程计数器rcpt302a和所述子线程计数器rccd306a是单独的计数器,分别负责跟踪来自父线程302和子线程306中的一个的引用。

在另一实施例中,父线程302依赖于子线程306以完成处理。也就是说,在其每个子线程完成处理之前,父线程302可能无法完成处理。在一个非限制性示例中,对于通知308父线程其已完成处理的子线程306,对所述对象abc(.1.)的所有引用必须完成(所述计数器的值为零),所述子线程306的子线程列表必须为空(表示不存在子线程),或者子线程306的所有子线程处于非活动状态(即完成处理)。

在另一实施例中,对所述父计数器rcpt302a和子计数器rccd306a的引用以无锁方式运行。某一对象被视为无锁的条件是其保证在具有多个线程试图对该对象执行操作的系统中,某些线程将在有限数量的系统步骤中成功完成操作,即使可能存在任意线程延迟,但前提是并非所有线程都无限期延迟(即,某些线程完成操作)。

凭借所述无锁操作,无需锁指令来更新相应的线程计数器rcpt302a和rccd306a,从而节省了大量开销。也就是说,通过实施无锁计数机制,可以避免与锁定相关的问题,包括性能瓶颈、对延迟和故障敏感、设计复杂以及在实时系统中出现优先级反转。

图3b示出了根据图3a的计数器的分层计数器数据结构。应理解的是,在接下来的讨论中,所公开的成员元素是非限制性的,并且可以添加或删除任何数量的不同成员元素。

当对象abc(.1.)初始是由单个线程(例如,父线程rc302)创建时,本地结构(structure,简称st)也作为所述父线程计数器rcpt302a的一部分创建。每个结构(此处称为分层计数器数据结构300a)包括初始化的成员元素,如下所述。

创建子线程rc306并为其传递了(分支)所述父线程rcpt302a对所述对象abc(.1.)的引用,所述子线程为所述子线程计数器rccd306a创建单独的分层计数器数据结构300a,例如,命名为ct_child,其中每个成员元素也被初始化。

所述分层计数器数据结构300a包括例如计数值的成员元素、所述对象的状态、子计数器列表和指针。应用图3b所示的成员元素,所述计数值(inuse)负责计算特定计数器对对象的引用数量。例如,如果所述计数值为零,则相应的线程不会进行引用。

所述对象的状态(isdead)确定对象是活动的(有效)还是非活动的(失效)。例如,当所述状态为true(isdead=true)时,所述对象将不再被引用且已失效。因此,对于状态为true的情况,所述当前线程和子线程可能没有对所述对象的任何引用。

子计数器(child_list)成员元素的列表负责列出父线程的每个子线程计数器。例如,如果父线程302有两个子线程且每个子线程都有自己的计数器,则所述父线程中的子计数器列表将指示(列出)这两个计数器作为其分层计数器数据结构的一部分。

指向直接父线程计数器的指针也是成员元素。按照具有两个子线程的父线程的示例,所述子线程计数器中的每个将包含指回直接(在这种情况下相同)父项的指针。

图3c示出了实现图3b的分层计数器数据结构的示例调用流程。所述调用流程300b是用于删除引用的更新顺序的示例。在一个非限制性实施例中,所述调用流程可以由应用服务器106n(图1)实现。但是,应理解的是,实现不限于所述应用服务器,图1中描述的任何各种组件都可以负责处理所公开的调用流程。

在示例实施例中,添加引用时,本地线程将更新所述对应的本地计数器(例如,子线程306更新子线程计数器rccd306a,使得inuse=inuse+1)。由于所述本地计数器由当前正在使用的本地线程更新或修改,因此其它线程读取/写入所述本地计数器时不存在数据竞争。删除引用时,将实现更具体的过程,如下所示。

所述调用流程300b演示了一个示例,其中ct设置为线程计数器(线程本地计数器),其中“inuse”指示对对象进行的引用数量的计数器值。当引用超出范围(不再存在)时,所述线程计数器ct将减少“1”(inuse-1)。接下来,检查每个成员元素,以确定它们是否满足各种条件。在调用流程300b的示例中,当所述线程计数器计数值为零时,所述服务器106n确定线程计数器ct(ct.children)的子计数器列表是null,还是所述子线程列表中的所有子线程都处于非活动状态。所述服务器106n还确定所述线程计数器ct的状态是否为true(非活动),所述指针是否为空(ct.parent=null表示不存在父级线程)。所述服务器106n还验证所述指针未引用任何父线程(即,所述线程是parent=null)。如果这些条件被满足,所述对象将被锁定和清除,所述进程将退出。否则,所述进程将继续,直到到达所述父线程(根线程)。

借助上述调用流程,删除对对象的引用时,数据竞争将被消除。尽管所述“isdead”值可以由多个线程从一个状态修改(翻转)为另一个状态(即,false到true),但如果完全是单向翻转,则会将状态从false翻转到true。此外,更新所述child_list依赖于inuse的值。也就是说,当inuse为“0”时,所述相应的线程计数不会被修改,但可能会被其它线程读取。否则,当inuse不是“0”时,只有所述当前线程可以通过将子项添加到所述child_list来修改它。此外,在一个实施例中,所述成员元素“指针”(表示父线程)在创建后为只读(即在所述计数器初始化期间设置所述值后)。

图3d示出了多线程进程的示例,其中将父线程302和子线程306引用数据(例如,对象abc(.1.))分配到存储器中。当所述对象abc(.1.)初始创建时,也会创建所述父线程计数器rcpt302a。在初始化期间,将所述分层计数器数据结构300a中的成员元素(也在图3d中由项目11、13、15、29和31表示)设置为初始值。例如,inuse=0,isdead=false,child_list={}和parent=null。每次所述父线程302的变量(例如“vara”)引用所述对象abc(.1.)时,向所述父线程计数器rcpt302a的所述分层计数器数据结构300a发送待更新的命令(例如,增量,即“inc”)(例如,修改所述分层计数器数据结构300a中的一个或多个成员元素)。在一个实施例中,所述增量在第一次引用所述对象时发生。

例如,当父线程302引用所述对象(vara=abc(.1.))时,所述父线程计数器rcpt302a从零值增加到计数值“1”(在11处,inuse=1)。

同样,在父线程302通过runtask{foo(a)}将“vara”(分支)传递到子线程306后,创建并初始化子线程计数器rccd306a,并且所述子线程计数器rccd306a从初始值0增加到值“1”(在23处,inuse=1)。此外,由于所述子线程306具有父线程302,因此还更新所述分层计数器数据结构300a以修改指向父线程计数器rcpt302a的指针(在图中标识为“c1”)。

例如,当所述子线程306的变量(varyy=aa)引用所述对象abc(.1.)时,所述子线程计数器rccd306a从计数值“1”增加到计数值“2”(在25处,inuse=2)。

所述对象abc(.1.)的后续引用也更新(例如,增加或减少)所述父线程计数器rcpt302a和子线程计数器rccd306a中的相应一个。同样,当对象被线程删除引用时,所述相应的父线程计数器rcpt302a和子线程计数器rccd306a将减少(decremented,简称“dec”)计数为“1”。

此外,应理解的是,对所述对象abc(.1.)的引用(包括后续引用)也可以对所述分层计数器数据结构300a中的其它成员元素发起更改。例如,当所述父线程302传递对所述对象abc(.1.)的引用时,向所述父线程计数器rcpt302a发送更新消息,修改所述分层计数器数据结构300a中的子项列表(在这种情况下,为项目13),以包括新创建的子线程306(child_list={c2},其中c2是指所述子线程计数器)。

如上所述,在一个实施例中,对所述父线程计数器rcpt302a和子线程计数器rccd306a的引用以无锁方式(即,无锁定)执行。

在另一实施例中,当所述子线程306引用所述对象abc(.1.)时,使得所述计数值为零,检查所述子线程306以确定处理是否已完成。例如,当所述子线程306中的最后一个变量(varyy)超出范围时,所述子线程计数器rccd306a降低到计数值零(inuse=0),并检查所述子线程以确定是否已完成处理,如下面参考图4a-4c和图5所示。

如果所述子线程306已完成处理,则检查所述父线程302以确定所述处理状态。类似于所述子线程计数器rccd306a,更新所述父线程计数器rcpt302a以反映已删除从所述父线程302到所述对象的引用。例如,当父线程302重新定义变量“a”以引用对象abc(.2.)(vara=abc(.2.))时,所述父线程计数器rcpt302a减少到计数1。在本示例中,所述分层计数器数据结构300a(在本示例中为项目19)中的计数值降至零(inuse=0)。所述计数值降至零后,检查所述父线程302以确定是否已完成处理,如下面参考图4a-4c和图5所述。如果处理完成,所述对象abc(.1.)可以从存储器中释放。

在一个实施例中,使用一个标志来指示所述对象是否已将abc(.1.)从存储器中释放(取消分配)。由于多个线程可以同时尝试释放同一对象,因此可以使用该标志来防止此类操作。例如,所述标志可以表示对象当前正在由另一个线程处理。为确保在处理期间不会更改所述标志,可以不在引用计数期间,而是在对象删除(取消分配)期间使用锁定机制。

图4a-4c示出了根据图1和图3a-3d中公开的实施例的参考计数流程图。在一个非限制性实施例中,应用服务器106n(图1)可以实现以下流程图中所公开的方法。所述应用服务器106n可以负责执行进程中访问分布式数据存储器的线程,该分布式数据存储包含用于处理的对象。但是,应理解的是,实现不限于所述应用服务器,图1中描述的任何各种组件都可以负责处理所公开的方法。

在402处,当对象abc(.1.)创建并分配给存储器,父线程计数器rcpt302a设置为计数引用(指向)所述对象abc(.1.)的线程数量。如上文所述,所述父线程计数器rcpt302a包括分层计数器数据结构300a,该结构跟踪线程对所述对象abc(.1.)的引用。所述父线程计数器rcpt302a的成员元素会根据所述线程发出的特定命令进行更新(例如,对计数值、状态、子列表和指针进行修改)。在一个实施例中,不使用锁定机制来保护对所述父线程计数器rcpt302a的更新。

在一个实施例中,当所述父线程302首先引用所述对象abc(.1.)时,发起所述父线程计数器rcpt302a。所述父线程计数器rcpt302a的初始化包括,例如,在402a处初始化所述分层计数器数据结构300a,如下面参考图4b所述。随后,所述父线程计数器rcpt302a跟踪对所述对象abc(.1.)做出和删除的引用。

在404处,当所述父线程302传递了(分支)406处对所述对象abc(.1.)的引用时,创建子线程306的子线程计数器rccd306a时。例如,当所述变量“a”由所述父线程302传递到所述函数runtask{(foo(a)}时,发起所述子线程306。

所述子线程计数器rccd306a还包括分层计数器数据结构300a。所述分层计数器数据结构300a以类似于父线程计数器rcpt302a的方式在404a处初始化,但所述初始值可以有所不同,如下面参考图4b所述。随后,所述子线程计数器rccd306a跟踪对所述对象abc(.1.)做出和删除的引用。

在所述父线程计数器rcpt302a和所述子线程计数器rccd306a处跟踪到的引用导致相应计数器的所述分层计数器数据结构300a更新,使得所述父线程计数器rcpt302a引用所述子线程计数器rccd306a,并且所述子线程计数器rccd306a指向所述408处的所述父线程计数器rcpt302a。在一个实施例中,从所述父线程计数器rcpt302a到所述子线程计数器rccd306a和指向所述父线程计数器rcpt302a的子线程计数器rccd306a的引用形成了分层结构,其可以表示为有向树图,其中所述父线程计数器rcpt302a是根节点,所述子线程计数器rccd306a是所述根节点的叶节点。当形成其它引用和指针时,所述定向树图将扩展以进一步形成所述分层结构。

在410处,所述服务器106n确定所述子线程306是否已完成所述对象abc(.1.)的处理。如果处理尚未完成,则该过程返回到408。否则,通知所述父线程计数器rcpt302a所述子线程306已在412处完成处理。

图4b示出了根据图3a和图4a的更新所述分层计数器数据结构的示例流程图。首次创建父线程计数器rcpt302a时,所述分层计数器数据结构300a将初始化。在一个实施例中,对所述分层计数器数据结构300a进行初始化,将计数值设置为初始值1,将父线程状态设置为活动、将子数据列表设置为空并将指针设置为空。子线程计数器rccd306a首次创建时也同样进行初始化。但是,对分层计数器数据结构300a初始化,需要将子计数值设置为初始值1,将父线程状态设置为活动,将子项表设置为空,并将指针设置为指向所述父线程计数器rcpt302a。

初始化后,所述分层计数器数据结构300a可以更新如下。在413处,当所述父线程302和子线程306对所述对象abc(.1.)引用或删除引用时,所述更新增加(参考添加)或减少(参考删除)所述父参考计数器rcpt302a和所述子参考计数器rccd306a中的一个。

在415处,所述更新更改所述父线程302和/或子线程306的状态。更改所述状态的更新包括将所述状态从活动状态更改为非活动状态。例如,当变量(例如,varaa)完成对所述对象abc(.1.)的处理时,所述子计数器rccd306a的状态(isdead)从false(活动)变为true(非活动)。在一个实施例中,状态的变化在一个方向上从活动变为非活动。

在417处,所述更新独立修改所述父线程302和/或所述子线程306的分层计数器数据结构300a中的子项列表,以添加或删除子项计数器。例如,当所述父线程302传递对所述对象的引用并将子线程306作为分支时,更新所述父线程计数器rcpt302a的所述分层数据结构300a,以指示所述子线程计数器rccd306a是所述子项列表中的子项。

与列出子项的父线程计数器类似,子线程计数器也同样指向父线程计数器。在419处,创建子线程计数器rccd306a时,更新所述分层计数器数据结构300a以指向所述直接父线程计数器rcpt302a。

图5示出了根据图3a–3b、图3d和图4a–4b的本地线程计数器的流程图的一个实施例。特别地,所述流程图演示了更新本地线程计数器的方法,例如父线程计数器rcpt302a和子线程计数器rccd306a。

通常,当将对象分配到存储器中时,初始化所述父线程302中的所述分层计数器数据结构300a(也在图3d中由项目11、13、15……29和31表示)。当所述父线程302将新线程(例如,子线程306)作为分支引用所述父线程302中的变量时,所述作为分支的子线程306初始化另一个(新的)分层计数器数据结构300a。一旦所述父线程计数器rcpt302a和子线程计数器(本地计数器)rccd306a已建立,则通过更新相应的本地线程计数器来跟踪引用。当本地线程计数器达到值“0”(零值)时,对所述对象的引用将不再保留在所述当前线程中。

例如,在502处,通过引用对象或取消引用对象来发起对本地线程计数器的更新。如果在504处线程引用(添加)对象,则所述本地线程计数器将在506处增加。如果所述对象在508处被线程删除引用(删除),则在510处所述本地线程计数器将减少。在任一情况下,如果所述本地线程计数器的所述计数值不等于零,则所述进程返回502。否则,如果所述本地线程计数器的所述计数值等于零,则已完成对所述对象的处理,该过程将在514处继续删除所述引用。

一旦所述计数值(inuse)降至零值(如在516处确定那样),则在518处检查所述分层计数器数据结构300a中的状态(isdead)值。例如,选中子项列表(child_list)以查看该列表是空还是列出了任何子项。如果子项列表不为空(child_list≠null)或所有列出的子列表不为非活动状态(对于所有列出的子列表为isdead≠true),则该过程将退出。也就是说,如果所述状态(isdead)=false(活动),因为至少有一个子线程的状态值“isdead”=false,则所述子线程306退出。否则,如果满足所述条件,所述程序将移至520,将所述本地线程计数器的状态设置为非活动(isdead=true)。例如,当“isdead”更改为true时(例如,所述线程已完成处理并超出范围)。

在522处,在确定所述本地线程计数器已完成处理后,检查所述分层计数器数据结构300a中的指针值。如果不存在指向父线程的指针(例如,pointer=null;由于存在指向父线程的指针,因此所述线程是根父线程,则所述根父线程(在图3d的示例中为父线程302)在526处锁定并删除所述引用的对象。否则,在524处,所述线程将继续向上遍历所述父线程,同时设置所述指针,直到到达所述根父线程。在一个实施例中,此遍历可实现为有向树图,其中所述根父节点是所述树的根节点,所述子节点是所述树中的叶。

图6是可用于实现各种实施例的网络设备600的框图。特定网络设备可利用所有所示的组件或仅利用所述组件的子集,且设备之间的集成程度可能不同。此外,所述网络设备600可以包含部件的多个实例,例如多个处理单元、处理器、存储器、发射器、接收器等等。所述网络设备600可以包括配备有一个或多个输入/输出设备例如网络接口和存储接口等的处理单元601。所述处理单元601可以包括中央处理器(centralprocessingunit,简称cpu)610、存储器620、大容量存储设备630,以及连接到总线670的i/o接口660。所述总线670可以是任意类型的若干总线架构中的一个或多个,包括存储总线或者存储控制器、外设总线等等。

所述cpu610可包括任何类型的电子数据处理器。所述存储器620可包括任何类型的系统存储器,如静态随机存取存储器(staticrandomaccessmemory,简称sram)、动态随机存取存储器(dynamicrandomaccessmemory,简称dram)、同步dram(synchronousdram,简称sdram)、只读存储器(read-onlymemory,简称rom)或其组合等。在一实施例中,所述存储器620可包括在开机时使用的rom,以及在执行程序时使用的存储程序和数据的dram。在各实施例中,所述存储器620是非瞬时的。在一个实施例中,所述存储器620包括创建模块620a、检查模块620b、更新模块620c、判断模块620d和通知模块620e;所述创建模块620a创建对应于父线程和子线程的父线程计数器和子线程计数器;所述检查模块620b检查本地线程计数器以确定所述成员元素的状态;所述更新模块620c更新所述本地线程计数器中的所述分层计数器数据结构;所述判断模块620d确定处理是否已完成;以及所述通知模块620e在子线程完成处理时通知父线程。

所述大容量存储设备630可包括任意类型的存储设备,其用于存储数据、程序和其它信息,并使这些数据、程序和其它信息可通过所述总线670访问。所述大容量存储设备630可包括如下项中的一种或多种:固态磁盘、硬盘驱动器、磁盘驱动器、光盘驱动器等。

所述处理单元601还包括一个或多个网络接口650,其可以包括诸如以太网线等的有线链路和/或用于访问节点或一个或多个网络680的无线链路。所述网络接口650允许所述处理单元601经由所述网络680与远程单元进行通信。例如,经由一个或多个发射器/发射天线和一个或多个接收器/接收天线,网络接口650可以提供无线通信。在一实施例中,所述处理单元601耦合到局域网或广域网上以用于数据处理以及与远程设备通信,所述远程设备例如其它处理单元、因特网、远程存储设施等。

在一示例实施例中,所述网络设备600包括父线程计数器模块、子线程计数器模块、计数器更新模块和通知模块;所述父线程计数器模块创建与父线程引用的对象对应的父线程计数器,所述父线程计数器包括分层计数器数据结构;所述子线程计数器模块创建子线程的子线程计数器,所述子线程计数器包括所述分层计数器数据结构,并将对所述对象的所述引用从所述父线程传递到所述子线程;所述计数器更新模块更新所述父线程计数器中的所述分层计数器数据结构以引用所述子线程计数器,并更新所述子线程计数器中的所述分层计数器数据结构以指向所述父线程计数器;以及当所述子线程完成处理时通知所述父线程计数器。在一些实施例中,所述网络设备600可以包括其它或者附加模块,用于执行所述实施例中描述的任一或组合的步骤。此外,如所述附图中的任意图所示或所述权利要求中任一项所述,所述方法中的附加或替代实施例或方面中的任意实施例或方面也预期包括类似的模块。

应该理解,本主题可以以许多不同的形式来体现,并且不应解释为限于在此阐述的实施例。相反,提供这些实施例是为了使本主题内容更加透彻和完整,并将本发明完整地传达给本领域技术人员。事实上,本主题旨在覆盖这些实施例的替代方案、修改和等同方案,其包括在由所附权利要求书定义的本主题的范围和精神内。此外,在本主题的下列具体描述中,列举了大量具体的细节,以对本主题有深入的了解。但是,本主题普通技术人员清楚的是,本发明可以在没有这些具体细节的情况下实施。

根据本发明的各实施例,本文所述的方法可以通过执行软件程序的硬件计算机系统实现。此外,在非限制性实施例中,实施方式可以包括分布式处理、部件/对象分布式处理和并行处理。可以构建虚拟计算机系统处理以实施本文所描述的方法或功能中的一种或多种,本文所描述的处理器可以用于支持虚拟处理环境。

此处,结合本发明实施例的方法、装置(系统)以及计算机程序产品的流程图和/或方框图描述本发明的各方面。应当理解,流程图和/或方框图的每个框以及流程图和/或方框图中的框的组合可以由计算机程序指令来实现。可以将这些计算机程序指令提供给通用计算机、专用计算机或其它可编程数据处理装置的处理器,以生成机制,使得这些通过计算机或其它可编程指令执行装置的处理器所执行的指令创建实现所述流程图和/或方框图中的一个或多个方框所指定的功能/动作的机制。

所公开技术的一个或多个非限制性优势是预分配多个计数器、利用对象分配和线程分支以及从根节点收集计数器数据结构。此外,所有计数器可以具有相同的数据结构,这有助于优化性能,例如预分配堆计数器并将其放入空闲列表中。分配新对象或线程分支时,可以从所述空闲列表请求所述计数器。鉴于所述计数器的树结构(分层结构),释放所述对象时,可以从所述根收集所述计数器数据结构。

此外,虽然本发明通常涉及垃圾收集,但所述系统不限于此类实施例。所述方法还可用于任何可能使用锁或多个客户端请求和/或使用资源的系统。也就是说,上述方法也可以在垃圾收集之外的系统中实现,且所述系统希望为此确保所述资源的所有用户都已完成使用,并且所述资源可以释放。

所述非瞬时性计算机可读介质包括所有类型的计算机可读介质,包括磁存储介质、光存储介质和固态存储介质,并且具体不包括信号。应当理解的是,软件可以安装在此处描述的设备上并可以随此处描述的设备一同出售。或者,可以获取软件并加载到设备中,包括通过光盘介质或以网络或分发系统的任何方式获取软件,例如,包括从软件开发者所有的服务器或从非软件开发者所有但为其所用的服务器获取软件。例如,该软件可以存储在服务器上以便通过因特网分发。

这里所使用的术语仅用于描述特定方面,而非旨在限制本发明。除非上下文中另有明确说明,本文使用的单数形式一个摂和所述摂包括复数含义。应进一步了解,术语“包括”和/或“包含”用于说明存在所述特征、整体、步骤、操作、元件和/或部件,但并不排除存在或添加一个或多个其它特征、整体、步骤、操作、元件、部件和/或它们的组合。

对本发明的描述只是为了说明的目的,而这些描述并不旨在穷举或限于所公开的实施例。在不偏离本发明的范围和精神的前提下,多种修改和变体对本领域技术人员而言是显而易见的。选择和描述本发明的各个方面以便更好地解释本发明的原理和实际应用,并且使本领域普通技术人员能够理解本发明和适合预期特定用途的各种修改。

为了本文档的目的,与所公开的技术相关联的每个过程可以连续执行并由一个或多个计算设备执行。过程中的每个步骤可以由与其它步骤中使用的相同或不同的计算设备执行,并且每个步骤不一定由单个计算设备执行。

虽然已经以特定于结构特征和/或方法动作的语言描述了主题,但是应理解,权利要求书定义的主题不必局限于上面描述的具体特征或动作。相反,上述具体的特征和动作被公开作为实施权利要求的示例性方式。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1