CN101685406A - 用于对数据结构的实例进行操作的方法和系统 - Google Patents

用于对数据结构的实例进行操作的方法和系统 Download PDF

Info

Publication number
CN101685406A
CN101685406A CN200810149826A CN200810149826A CN101685406A CN 101685406 A CN101685406 A CN 101685406A CN 200810149826 A CN200810149826 A CN 200810149826A CN 200810149826 A CN200810149826 A CN 200810149826A CN 101685406 A CN101685406 A CN 101685406A
Authority
CN
China
Prior art keywords
lock
data structure
weak
strong
operations
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.)
Pending
Application number
CN200810149826A
Other languages
English (en)
Inventor
甘志
齐尧
戴晓君
邱模炯
王远洪
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
International Business Machines Corp
Original Assignee
International Business Machines Corp
Priority date (The priority date 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 date listed.)
Filing date
Publication date
Application filed by International Business Machines Corp filed Critical International Business Machines Corp
Priority to CN200810149826A priority Critical patent/CN101685406A/zh
Priority to PCT/EP2009/062391 priority patent/WO2010034777A1/en
Publication of CN101685406A publication Critical patent/CN101685406A/zh
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements 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/46Multiprogramming arrangements
    • G06F9/52Program synchronisation; Mutual exclusion, e.g. by means of semaphores
    • G06F9/526Mutual exclusion algorithms

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Information Retrieval, Db Structures And Fs Structures Therefor (AREA)

Abstract

本发明提供了一种对数据结构的实例进行操作的方法和系统。该方法包括为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作。响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作。为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作。响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。根据本发明的上述方法和系统可以提高对数据结构的实例进行操作的效率。

Description

用于对数据结构的实例进行操作的方法和系统
技术领域
本发明涉及对多线程软件的开发和处理,尤其涉及对数据结构的实例进行操作的方法和系统。
背景技术
在过去的二十多年的时间里,随着微电子技术的迅猛发展,计算机系统的性能和容量发生了爆炸性的增长。较多的计算资源意味着可以按并行的方式来同时执行更多的操作。因此,并行的体系结构以及并行的软件开发,在信息处理中发挥越来越核心的作用。
一个进程是在计算机系统上运行的一个程序或程序的一部分,或者是被某个程序执行的步骤的相关序列。每个进程包括一个或多个线程。线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行。所以线程基本上是轻量级的进程,它负责在单个程序里执行任务。通常由操作系统负责多个线程的调度和执行。
数据结构是一种数据的组织方案,例如记录或数组,籍此有助于解释数据或执行对数据的操作。一数据结构的一实例,是指一种数据结构的具体实施对象。对数据结构的实例的处理,在进程或程序中经常采用多线程处理,这可以充分利用系统资源,缩短程序响应时间,改善用户体验;如果程序中只使用单线程,那么程序的速度和响应无疑会大打折扣。多线程软件使得多个线程可以并行的工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。但是,程序采用了多线程后,就必须认真考虑线程调度的问题。如果调度不当,要么造成程序出错,要么造成荒谬的结果。众所周知,与顺序执行的软件相比,多线程软件更加难以开发。
由于多个线程之间可能存在的未预料到的冲突,具有并行体系结构的程序经常包含程序缺陷。尤其是,如果没有合适的同步机制,并行地访问共享的数据结构将产生无法预料的错误。到目前为止,人们通常使用两种方法来开发多线程软件。基于锁(lock-based)的方式和无锁(lock-free)的方式。
对于多线程编程和多线程并行处理,基于锁的方式是一种传统的方法。该方法利用加锁来实现同步,以便对共享资源进行访问。常用的同步原语(Synchronization primitives)如互斥体(mutexes)、旗语(s emaphores)和关键部件(critical sections)。这些同步原语通常被用于确保某些特定的部分代码不会被同时执行,否则将会破坏共享存储结构。如果一个线程试图获取已经被其它线程持有的锁,则该一个线程将会被阻塞(block)直至该锁被释放为止。例如,在程序中,很多任务必须以确定的先后秩序执行,对于两个线程必须以先后秩序执行的情况,可以用线程锁来处理。线程锁的大致思想是:如果线程A和线程B会分别执行实例的两个函数a和b,如果A必须在B之前运行,那么可以在B进入b函数时让B进入wait set,直到A执行完a函数再把B从wait set中激活。这样就保证了B必定在A之后运行,无论在之前它们的时间先后顺序是怎样的。
互斥锁(mutual-exclusion locks)是目前常用的一种机制,用于进程或线程间的同步。其简单并且容易实施。在高性能应用的并行计算环境里,这种简易性则无法实现。当使用大量的锁并且有许多线程并行执行时,互斥锁的可扩展性不佳。对于共享数据的并行访问,需要复杂的细粒度的锁策略,来将没有冲突的操作设置为并行执行。要保持良好的性能,这种策略很难设计,并且可能隐含问题,如死锁或优先级倒置。
由于多种已知的原因,使得不希望线程被阻塞。一个明显的原因是,如果一个线程被阻塞,则该线程在该期间无法完成任何任务。如果被阻塞的线程正在执行一个高优先级的任务,或者正在执行一个实时的任务,就更加不希望该线程被阻塞。
此外,多个锁之间的某些冲突还可能导致一些错误的状态,如死锁、活锁或优先级倒置(deadlock,live-lock,or priority inversion)。使用锁还涉及在粗粒度的锁和细粒度的锁两个方面之间进行折衷,粗粒度的锁可能会显著减少并行执行的机会,细粒度的锁需要更加细致的设计并且容易程序缺陷。
不加锁(lock-free)的方式是多线程软件的开发和处理的另一种选择。Lock-free和wait-free机制,主要使用由硬件提供的原子原语。大部分通用的硬件均提供这种原子原语指令集。“比较并交换(compare and swap,即CAS)”是最常用的原子原语之一。该原子原语使用三个参数(argument):一个内存地址、一个原始值(已有值)和一个新的值。如果上述内存地址存有一个原始值,则用新的值替换该原始值,否则存储的值不变。重要的是,硬件确保“比较并交换”操作被原子地执行。该操作的成功执行将返回一个值1或0,并被汇报给程序。这允许一个算法从内存中读取数据,修改该数据,然后只有在没有其它线程同时修改该内存的数据的情况下写回修改后的数据。上述基于锁的方法和不加锁的方法,各有如下优缺点。
  基于锁的方法(Lock-basedapproach)  无锁的方法(Lock-freeapproach)
  可扩展性   不好。在进入和离开程序关键部分时,线程需要等待。  好。有多个线程在执行。
  鲁棒性   不好。一个线程的异常退出可能会阻碍其它线程。例如,死锁。  好。即使一个线程死掉,其它线程仍然得以执行。
  容易开发性   相对容易。线程的算法(机制)与顺序执行的线程相似。获得锁的线程可以阻塞其它未得到锁的线程的执行。  非常困难。线程的算法(机制)与顺序执行的线程经常完全不同。并且,有些操作效率非常低。经常需要证明线程之间的复杂逻辑的正确性。
此外,Fraser提到了一种基于MCAS和W-Locks的混合机制(见Practicallock-freedom,by Keir Fraser,2004)。运行时的性能反馈被用于根据当前的竞争水平动态选择使用哪种机制。该机制中使用了运行时概要和同步原语之间的切换。
发明内容
鉴于已有技术的不足,本发明提供了一种新的对数据结构的实例进行操作的方法和系统。
对数据结构的实例进行操作的方法包括:为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作;响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作;为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作;以及响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。
本发明还提供了一种对数据结构的实例进行操作的系统。该系统包括:弱锁装置,用于为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作;可无锁的操作执行装置,用于响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作;强锁装置,用于为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作;以及不应无锁的操作执行装置,用于响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。
与已有技术相比,根据本发明的上述方法和系统可以提高对数据结构的实例进行操作的效率。
附图说明
图1a示意性地示出了已有技术中基于锁的方法的机制。
图1b示意性地示出了已有技术中无锁实现的方法。
图2a示意性地示出了已有技术中基于锁的方法的异常退出的情况。
图2b示意性地示出了已有技术中无锁实现的方法的异常退出的情况。
图3示出了根据本发明一实施例的用于数据结构的实例进行操作的方法。
图4a和图4b示出了根据本发明一实施例的操作执行情况。
图5a和图5b示出了与本发明实施例相对比根据已有技术的一实施例的操作执行情况。
具体实施方式
数据结构是一种数据的组织方案,例如记录或数组,籍此有助于解释数据或执行对数据的操作。一数据结构的一实例,是指一种数据结构的具体实施对象。对于涉及多线程处理的一数据结构或数据结构实例,为了确保在多线程之间该数据结构的一致性(Coherence)或对该数据结构实例操作的正确性,对该数据结构加锁是一种常用的方法。本发明也采用加锁的方式来确保对数据结构操作的正确性。本发明所利用的锁的原理本身或用锁来保护数据结构的锁机制本身,与已有技术相比是相似的。例如,对于需要获取锁才能处理的数据结构实例,只有一操作获取锁之后才能进行处理。对于何种操作进行加锁,附加何种类型的锁,本发明的一实施例在这两方面与已有技术是不同的。此外,根据本发明的另一实施例,在获取不同类型的锁之后,持有锁的操作所允许执行的操作与已有技术相比是不同的。以下结合附图详细说明。
不同的已有技术在何种情况下需要锁,采取了不同的策略。例如,基于锁的方法,所有的进程或操作都用锁来保护。这样,能够确保所涉及的数据结构的安全性,但是,可扩展性较低。如图1a和图2a所示。
图1a示意性地示出了已有技术中基于锁的方法的机制。其中,有四个线程a1、a2、a3和a4需要执行。如果线程a1获取了锁并开始执行,则其它三个线程被阻塞。在线程a1完成执行后,释放所持有的锁。这时,其它三个线程尝试获取锁。与线程a1类似,获取锁的进程执行,其它线程被阻塞。这样,在进入和离开程序关键部分时,多个线程需要等待。线程的算法或机制与顺序执行的线程相似。获得锁的线程可以阻塞其它未得到锁的线程的执行。但是,如图2a所示,这种基于锁的方式的鲁棒性确不好。
图2a示意性地示出了已有技术中基于锁的方法的异常退出的情况。其中,一个持有锁的线程,如线程1a,异常退出可能会阻碍其它线程。例如,线程1a发生死锁,其持有的锁未被释放,则其它等待的线程就会长时间处于不必要的等待状态。
根据已有技术对于锁的一个具体应用如下例1。例如,一个传统的堆栈具有如下的布局。对于已有技术的多线程或多操作的并行处理,这样的堆栈是不安全的。
例1
  Stack instance:
  top:Node
  size:int
  ...
为确保对该堆栈操作的正确性,根据已有技术可以采用如下例2加锁(lock:LockType)的方式来进行。例如,在堆栈的实例上加锁。这样,在对该堆栈进行操作前,首先请求获取该锁。获取锁的操作或线程,可以对该堆栈进行操作,并在操作完成后释放锁。这时,其它需要对该线程进行的操作被阻塞,这些被阻塞的线程可以反复尝试获取锁,直至得到锁为止。
例2
  Stack instance:
  lock:LockType
  top:Node
  size:int
  ...
对于每个堆栈的操作,如push()、pop()或clone()等等,可以调用lock.lock()来请求获取锁,调用lock.unlock()来释放锁。这样,可以确保每次只有一个线程对堆栈进行操作。
在根据本发明的一实施例中,如下例3所示,可以采用与已有技术中设置读锁和写锁类似的方法,将该锁设置为包括弱锁rLock:WeakLock和强锁wLock:StrongLock。其中,可以允许有多个操作/线程同时分别持有该锁的多个弱锁,但是只允许一个操作/线程持有该锁的强锁,不允许该锁的弱锁和强锁同时被持有。持有弱锁或强锁的操作可以对该堆栈进行操作,操作完成之后,释放其持有的锁。此外,持有所述该弱锁的多个操作可以并行执行,如图1b、图2b和图4a所示。而持有强锁的一操作对该堆栈进行操作时,其它需要对该堆栈进行的操作将被阻塞。这些被阻塞的操作可以尝试获取锁,如周期性地进行尝试。持有弱锁的操作对该堆栈进行操作时,其它请求获取强锁的操作将被阻塞,而其它请求获取弱锁的操作可以继续获得弱锁。同样,这些被阻塞的操作可以尝试获取强锁,如周期性地进行尝试。
例3
  Stack instance:
  wLock:WeakLock   sLock:StrongLock
  top:Node
  size:int
  ...
图1b示意性地示出了已有技术中无锁(Lock-free)实现的方法。无锁的方法的出发点是为了克服基于锁的方法扩展性不好的缺陷。如图1b所示,在无锁的方法中,多个线程b1、b2、b3和b4可以并行执行,从而提高进程或程序的执行效率。无锁方法不但可扩展性好,而且鲁棒性也好,如图2b所示。
图2b示意性地示出了已有技术中无锁实现的方法的异常退出的情况。如图2b所示,即使一个线程b1死掉,其它线程b2、b3和b4仍然得以执行。但是,无锁方法的开发却非常困难。无锁方法的线程的算法或执行机制与顺序执行的线程经常完全不同。因此,经常需要证明无锁线程之间的复杂逻辑的正确性。并且,有些操作采用无锁的方法,其执行效率非常低。
根据本发明的一实施例,将无锁的并行执行机制和加锁顺序执行机制结合来进行多线程软件的处理。本领域的技术人员可以理解,可以在硬件上、操作系统中或应用程序中设置锁的保护范围或作用域。如已有技术中,通过设置读锁rLock:ReadLock和写锁wLock:WriteLock的保护范围或作用域,使得持有读锁的操作可以并行执行读取操作,而持有写锁的操作可以排他性地执行其操作。
本领域的技术人员可以理解,可以采取与已有技术类似的方法,在硬件上、操作系统中或应用程序中设置弱锁和强锁的保护范围或作用域,使得持有弱锁的多个操作可以并行执行其操作,而持有强锁的一操作排他性地执行其操作。如在上述例3中,通过设置弱锁wLock:WeakLock和强锁sLock:StrongLock的保护范围或作用域,使得持有弱锁的多个操作可以并行地执行其操作,而持有强锁一操作则排他性地执行其操作。在这种情况下,多线程程序或进程的可扩展性、鲁棒性或容易开发性,可以通过进一步的机制来确保。
图3示出了根据本发明一实施例的用于数据结构的实例进行操作的方法。在步骤S100,开始该方法。在步骤S110,将对数据结构的一实例的操作划分为可无锁的操作(lock-free capable operation)和不应无锁的操作(lock-freeincapable operation)。如下文所述,可以采用多种方式将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。本领域的技术人员可以理解,该步骤的实施可以由软件的开发工具或程序的执行环境来实施,而独立于其它步骤S120-S160。
此外,如上文所述可以程序之中,或程序的执行环境中(如上文所述的在硬件上、操作系统中或应用程序中)设置锁的作用方式。其中,允许有多个操作/线程同时分别持有第一锁的多个弱锁,只允许一个操作/线程持有第一锁的强锁,不允许第一锁的弱锁和强锁同时被持有;其中,持有所述第一锁的弱锁的多个可无锁的操作并行执行。其中,一可无锁的操作所执行的操作可以包括写操作。亦即,根据本发明的一实施例,允许有的可无锁的操作只包括读操作而有的可无锁的操作包括写操作。另,在本发明的上述描述中使用的术语“第一锁”的实质含义是指一锁,使用“第一”是为了指代的需要。如文中使用“该第一锁”指代前述的“第一锁”,以避免在相应的上下文中使用“该锁”时不易指明是指代前述的“一锁”还是指代前述的“弱锁”等。
在步骤S120,为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作。如果其它操作已经持有该第一锁的弱锁,则允许该至少一可无锁的操作获取该第一锁的另一弱锁。如果其它操作已经持有该第一锁的强锁,则该至少一可无锁的操作将被阻塞,直至该强锁被释放为止。本领域的技术人员可以理解,根据本发明实施例的锁的使用方法,还可以与其它锁的分配机制相结合,如与根据优先级来分配锁的机制相结合,等等。
在步骤S130,响应于该至少一可无锁的操作完成获取弱锁,执行该可无锁的操作对该数据结构的实例进行的操作。根据本发明的一实施例,允许有的可无锁的操作只进行读操作而有的可无锁的操作进行写操作。根据本发明的另一实施例该方法还可以进一步包括:响应于该可无锁的操作完成对该数据结构的实例的操作,释放该弱锁。
在步骤S140,为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作。如果其它操作已经持有该第一锁的弱锁或强锁,则该不应无锁的操作将被阻塞,直至该弱锁或强锁被释放为止。
在步骤150,响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。根据本发明的另一实施例该方法还可以进一步包括:响应于该不能无锁的操作完成对该数据结构的实例的操作,释放该强锁。在步骤160,该方法结束。
本领域的技术人员可以理解,步骤S120-S160本身已经构成了一个完整的技术方案,而直接在相应的具有上述强锁和弱锁的运行环境或工具软件上实施。
一数据结构的一实例,是指一种数据结构的具体实施对象。链表是一种常用的数据结构,其它常用的数据结构还包括顺序表、树、图、跳表等等。“链表”是一个链表结构,链表中的每个节点都含有指向下一个节点的指针。数据结构“链表”的操作通常有增加元素,删除元素,查询元素,遍历元素,排序。在本发明的实施例中对一链表的实例list进行举例说明,该list中包括多个元素。
根据本发明的一实施例,可以使用强锁和弱锁来保护List类。通过设置弱锁和强锁的保护范围或作用域,使得持有弱锁的多个操作可以并行地执行其操作,而持有强锁一操作则排他性地执行其操作。对于可无锁的操作add()和remove(),可以使用弱锁以便多个可无锁的操作可以并行执行。对于不应无锁的操作使用一强锁,来排他性地访问List,阻塞其它操作对于List的访问。
下面举例说明可无锁的操作和不应无锁的操作。在下述实施例中,操作add是可无锁的操作,操作remove是可无锁的操作,而操作sort是不应无锁的操作。操作add获取针对List的弱锁之后,操作remove依然可以获取针对List的弱锁。因此,操作add和操作remove可以并行执行。操作sort不能与操作add或操作remove并行执行。
class List{
      private Lock weaklock,stronglock;
      public List(){
           WeakStrongLock wslock=new WeakStrongLock();
           weaklock=wslock.weaklock();
           stronglock=wslock.stronglock();
      }
在上述程序中,首先定义List类,然后private Lock weaklock,stronglock为针对该List类的操作定义一锁。在该程序被初始化时将派生一锁WeakStrongLockwslock=new WeakStrongLock(),该锁包括一个或多个弱锁weaklock=Wslock.weaklock()和一个强锁stronglock=wslock.stronglock()。
public void add(Obj ect obj){
     try{
          weaklock.lock();
          //do the lock-free add
     }finally{
          weaklock.unlock();
     }
}
在上述程序中,将对象obj加入List的操作add,可以由一个或多个原子操作组成。因此,操作add是可无锁的操作。在执行时,首先使用weaklock.lock()请求弱锁。获取弱锁之后,执行可无锁的操作add,将对象obj加入List;执行完成后,weaklock.unlock()释放弱锁。
如果该锁的强锁被其它的操作或线程持有,add操作将被阻塞。然后,在该锁的强锁被释放后,该add操作才能获取所请求的弱锁。
public void remove(Obj ect obj){
     try{
           weaklock.lock();
           //do the lock-free remove
     }finally{
           weaklock.unlock();
     }
}
在上述程序中,将对象obj从List删除的操作remove,可以由一个或多个原子操作组成。因此,操作remove是可无锁的操作。在执行时,首先使用weaklock.lock()请求弱锁,获取弱锁之后,执行可无锁的操作remove;执行完成后,weaklock.unlock()释放弱锁。如果该锁的强锁被其它的操作或线程持有,则该remove操作将被阻塞。然后,在该锁的强锁被释放后,该remove操作才能获取所请求的弱锁。但是,如果该锁的一弱锁被其它的操作或线程持有,则该remove操作可以获取该锁的另一弱锁。
public void sort(){
     try{
          stronglock.lock();
          //do sorting
     }finally{
          stronglock.unlock();
     }
   }
}
在上述程序中,将类List的对象obj排序的操作sort,不能分解为一个或多个原子操作。其所需的原子操作数量将随着List中元素数量变化而变化。因此,操作sort是不应无锁的操作。在执行时,首先使用stronglock.lock()请求强锁,获取强锁之后,执行不应无锁的操作sort;执行完成后,stronglock.unlock()释放强锁。如果该锁的强锁或弱锁被其它的操作或线程持有,则该sort操作将被阻塞。然后,在该锁的强锁或弱锁其它操作或线程被释放后,该sort操作才能获取所请求的强锁。
上述图3的方法中,步骤S110将对数据结构的实例的操作划分为可无锁的操作和不应无锁的操作可以采用多种方法来进行。
根据本发明的一实施例,如果一个操作的无锁算法需要的原子操作的数目是一个常数,则将该操作划分为可无锁的操作;如果一个操作的无锁算法需要的原子操作的数目不是一个常数,则将该操作划分为不应无锁的操作。在本发明的进一步实施例中,如果一个操作的无锁算法需要的原子操作的数目是一个常数,并且该常数与数据结构的实例中元素的数目不相关,则将该操作划分为可无锁的操作;如果一个操作的无锁算法需要的原子操作的数目不是一个常数,该数目与数据结构的实例中元素的数目相关,则将该操作划分为不应无锁的操作。
其中,可无锁的操作对数据结构的实例的操作可以分解为由预定数量的原子操作组成的操作。优选地,可无锁的操作对数据结构的实例的操作可以分解为由1-5个原子操作组成的操作。其中,不应无锁的操作对数据结构的实例的一操作,不能分解为由一个或多个原子操作组成的操作。
如上述处理List的例子中,元素的添加操作只需要一个原子操作,而元素的删除操作只需要一个或两个原子操作。因此,这两种操作可以划分为可无锁的操作。而List的排序操作和数据结构中的元素数目相关,因而属于不应无锁操作。再如,在堆栈或出栈(push or pop in stack)可以划分为可无锁的操作;而为图形加边框的操作应划分为不应无锁操作。
在本发明之前的已有技术中,对于基于锁的方法都用锁保护。这样数据结构是安全的,但是可扩展性较低。而如果数据结构中的部分操作是无锁而且是多线程安全的,例如List的add()和remove()方法。而其他操作不是多线程安全的,如List的sort()方法。这样数据结构的使用将相当受限。程序员使用非线程安全的方法需要非常小心,必须等待直到一个安全的时间,并在这个安全的时间之内调用非线程安全的方法。这种方式需要程序员过多的介入,不管是开发效率还是执行效率都受到影响。
根据本发明的另一实施例,如果一个操作需要修改的内存单元的数目是一个常数,则将该操作划分为可无锁的操作;如果一个操作的需要修改的内存单元的数目不是常数,则将该操作划分为不应无锁操作。根据本发明的进一步实施例,可无锁的操作需要修改的内存单元的数目与数据结构中元素的数目不相关,不应无锁操作需要修改的内存单元的数目与数据结构的实例中元素数目相关。优选地,可无锁的操作的内存单元访问少于一个字或者一个双字;不应无锁操作的内存单元访问多于一个双字或两个不连续的字。
对于上述处理List的例子,元素的添加操作只需要修改原List中的一个指针变量,List的删除操作只需要修改List中一个或两个指针变量。因此,这两种操作被划分为可无锁的操作。而List的排序操作需要修改的指针数量正比于List中的元素数目,因而属于不应无锁操作。
根据本发明的另一实施例,在单线程执行时,对于同一个数据结构实例的每一个操作,如果以无锁的方式实现时的执行效率,与基于锁的方式实现时的执行效率相差小于预定的值,则将该操作划分为可无锁的操作;否则,将该操作划分为不应无锁的操作。优选地,在单线程执行时,如果对于同一个数据结构实例的每一个操作,以无锁的方式实现时的执行效率,与基于锁的方式实现时的执行效率相差小于1.5倍,则将该操作划分为可无锁的操作;否则,将该操作划分为不应无锁的操作。
对于同一个数据结构的每一个操作都可以实现两个版本,一个为无锁实现,令一个为基于锁的实现。在上述处理List的例子中,元素的添加操作和删除操作的效率和基于锁的实现差不多。所以划分为可无锁操作。而List的排序操作的无锁实现相当低效,所以划分为不应无锁操作。此外,为图形加边框的操作,如果采用无锁的方式,效率也非常低。
根据本发明的另一实施例,在图3所示的方法中,允许有多个操作/线程同时分别持有第一锁的多个弱锁,只允许一个操作/线程持有第一锁的强锁,不允许第一锁的弱锁和强锁同时被持有;其中,持有所述第一锁的弱锁的多个可无锁的操作并行执行。其中,图3所示的方法进一步包括:响应于该可无锁的操作完成对该数据结构的实例的操作,释放该弱锁;响应于该不能无锁的操作完成对该数据结构的实例的操作,释放该强锁。
图4a和图4b示出了根据本发明一实施例的操作执行情况。在图4a中,两个或多个可无锁的操作被并行执行,此时,一个或多个不应无锁的操作被阻塞。如图4a中所示的操作add()和remove()等操作被并行执行,此时不应无锁的操作size()等被阻塞。在图4b中,一个或多个不应无锁的操作被顺序执行,此时,其它不应无锁的操作以及可无锁的操作被阻塞。如图4b中所示的操作size()等操作被顺序执行,此时其他不应无锁的操作以及可无锁的操作add()和remove()等被阻塞。
在本发明之前的已有技术中,无锁的方法具有多种优点,但是却难以开发。因此,无锁机制经常被用于简单的操作。例如,参见以下采用已有技术对于一数据结构的实例--链表List类-的操作。
class List{
public void add(Object obj);
public void remove(Obj ect obj);
public void sort();
}
将无锁机制用于add()和remove()方法并不难。add()用于增加一元素,publicvoid add(Object obj)表示为List类增加一对象元素,并且该List的add可以被其它线程的操作访问。remove()用于删除一元素,public void remove(Object obj)表示为List类删除一对象元素,并且该List的remove可以被其它线程的操作访问。sort()用于对元素进行排序操作,public void sort()表示将List的对象元素进行排序,并且该List的sort可以被其它线程的操作访问。但是,将无锁机制用于sort()方法就很难。原因数据结构实例List一般包括多个元素。这样,在执行List元素排序操作的过程中,如果其它线程对List的对象元素进行增加或删除操作,将引起冲突。
因此,自然的方法是使用锁来保护sort()。这样,重写后的代码如下。
class List{
public void add(Object obj);
public void remove(Object obj);
public synchronized void sort();
}
public synchronized void sort()表示在sort执行时需要加锁和释放锁(lockunlock pair)的操作。在此,将sort()修改为同步的方法,在执行时,首先尝试获取一锁;在获取锁之后,执行排序操作;在排序操作完成后,释放该锁。这样,在任何时候只有一个线程被允许进入该方法调用sort。但是,上述方法并非正确。如果一个线程进入sort()方法,这时另一个线程使用remove()方法来删除一个节点,sort方法将可能失效。
因为,add()方法可能在某个时刻与sort()方法交叉。并且,尽管sort()方法加锁;但是,add是无锁的。这就允许add在任何时刻都可以执行,从而由可能产生冲突。因此,安全的版本将采用如下方式,其中对所有操作采取同步(或加锁)的方式进行。
class List{
public synchronized void add(Object obj);
public synchronized void remove(Object obj);
public synchronized void sort();
}
public synchronized void add(Object obj)表示在add执行时需要加锁和释放锁(lock unlock pair)的操作。public synchronized void remove(Object obj)表示在remove执行时需要加锁和释放锁(lock unlock pair)的操作。现在,得到了安全的List。但是,其中的全部三个方法都使用锁来保护。这样,如图1和图2所示,在任何时刻,只允许一个线程进入上述三个方法之一。在图1中,简单操作获取一个互斥锁,并阻止其它操作获取该互斥锁。在图2中,复杂操作获取一个互斥锁,并阻止其它操作获取该互斥锁。这种方式妨碍了软件并行执行。
图5a和图5b示出了与本发明实施例相对比根据已有技术的一实施例的操作执行情况。该已有技术采用加锁操作。在图5a中,由于add()需要执行写操作,而并非单纯的读操作,因此,得到锁的操作add()被执行时,其它的操作将被阻塞。在图5b中,由于size()需要执行写操作,而并非单纯的读操作,因此,得到锁的操作size()被执行时,其它的操作将被阻塞。
与上述一种对数据结构的实例进行操作的方法相对应,本发明还提供了一种对数据结构的实例进行操作的系统,包括:弱锁装置,用于为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作;可无锁的操作执行装置,用于响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作;强锁装置,用于为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作;以及不应无锁的操作执行装置,用于响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。
其中,弱锁装置和强锁装置进一步配置为:允许有多个操作同时分别持有该第一锁的多个弱锁,只允许一个操作持有该第一锁的强锁,不允许该第一锁的弱锁和强锁同时被持有;可无锁的操作执行装置配置为允许持有该第一锁的弱锁的多个可无锁的操作并行执行。
其中,上述系统进一步包括阻塞装置,该阻塞装置配置为:响应于执行该不应无锁的操作,阻塞请求该第一锁的强锁的操作;响应于执行该不应无锁的操作,阻塞请求该第一锁的弱锁的操作或其它请求该第一锁的强锁的操作。
其中,所述弱锁装置进一步配置为:响应于该可无锁的操作完成对该数据结构的实例的操作,释放该弱锁;所述强锁装置进一步配置为响应于该不能无锁的操作完成对该数据结构的实例的操作,释放该强锁。
其中,可无锁的操作所执行的操作可以包括写操作。
其中,上述系统进一步包括操作划分装置,用于将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。操作划分装置可以进一步配置为使用根据上文所述的多种方法的一种或多种,将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。
与已有技术相比,本发明将基于锁的方法和无锁的方法的并行处理进行整合。如上文所述,无锁的代码并行执行可扩展性好,但是难以编程。与此相反,基于锁的方法可扩展性差,但是却容易理解和编程。当多个可无锁的操作在多个线程中并行执行时,可无锁的操作能够确保原子操作特性和共享变量的一致状态。当一个不应无锁的操作与其它不应无锁操作或可无锁操作需要执行时,用一个强锁来确保原子操作特性和共享变量的一致状态。
根据本发明的一个实施例,当只有简单的方法而没有复杂操作执行时,可无锁操作就可以并行执行。可以针对全部数据结构安全地并行执行操作。当复杂方法执行时,仍然可以利用强锁来针对全部数据结构安全地执行线程。可无锁操作不会受到不必要的阻止。
本发明还提供了一种存储介质或信号载体,其中包括用于执行根据本发明的方法的指令。
以上结合优选法方案对本发明进行了详细的描述,但是可以理解,以上实施例仅用于说明而非限定本发明。本领域的技术人员可以对本发明的所示方案进行修改而不脱离本发明的范围和精神。

Claims (22)

1.一种对数据结构的实例进行操作的方法,包括:
为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作;
响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作;
为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作;以及
响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。
2.根据权利要求1所述的方法,其中,允许有多个操作同时分别持有该第一锁的多个弱锁,只允许一个操作持有该第一锁的强锁,不允许该第一锁的弱锁和强锁同时被持有;其中,持有该第一锁的弱锁的多个可无锁的操作并行执行。
3.根据权利要求2所述的方法,其中进一步包括响应于执行该不应无锁的操作,阻塞请求该第一锁的强锁的操作;响应于执行该不应无锁的操作,阻塞请求该第一锁的弱锁的操作或其它请求该第一锁的强锁的操作。
4.根据权利要求1所述的方法,其中进一步包括:响应于该可无锁的操作完成对该数据结构的实例的操作,释放该弱锁;响应于该不能无锁的操作完成对该数据结构的实例的操作,释放该强锁。
5.根据权利要求1所述的方法,其中可无锁的操作所执行的操作可以包括写操作。
6.根据权利要求1所述的方法,其中进一步包括:将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。
7.根据权利要求1至6任一项所述的方法,其中,如果一个操作的无锁算法需要的原子操作的数目是一个常数,则将该操作划分为可无锁的操作;如果一个操作的无锁算法需要的原子操作的数目不是一个常数,则将该操作划分为不应无锁的操作。
8.根据权利要求7所述的方法,其中,如果一个操作的无锁算法需要的原子操作的数目是一个常数,并且该常数与数据结构的实例中元素的数目不相关,则将该操作划分为可无锁的操作;如果一个操作的无锁算法需要的原子操作的数目不是一个常数,该数目与数据结构的实例中元素的数目相关,则将该操作划分为不应无锁的操作。
9.根据权利要求7所述的方法,其中,可无锁的操作对数据结构的实例的操作可以分解为由预定数量的原子操作组成的操作。
10.根据权利要求7所述的方法,其中,可无锁的操作对数据结构的实例的操作可以分解为由1-5个原子操作组成的操作。
11.根据权利要求1至6任一项所述的方法,其中,如果一个操作需要修改的内存单元的数目是一个常数,则将该操作划分为可无锁的操作;如果一个操作的需要修改的内存单元的数目不是常数,则将该操作划分为不应无锁操作。
12.根据权利要求11所述的方法,其中,可无锁的操作需要修改的内存单元的数目与数据结构中元素的数目不相关,不应无锁操作需要修改的内存单元的数目与数据结构的实例中元素数目相关。
13.根据权利要求11所述的方法,其中,可无锁的操作的内存单元访问少于一个字或者一个双字;不应无锁操作的内存单元访问多于一个双字或两个不连续的字。
14.根据权利要求1至6任一项所述的方法,其中,在单线程执行时,对于同一个数据结构实例的每一个操作,如果以无锁的方式实现时的执行效率,与基于锁的方式实现时的执行效率相差小于预定的值,则将该操作划分为可无锁的操作;否则,将该操作划分为不应无锁的操作。
15.根据权利要求14所述的方法,其中,在单线程执行时,如果对于同一个数据结构实例的每一个操作,如果以无锁的方式实现时的执行效率,与基于锁的方式实现时的执行效率相差小于1.5倍,则将该操作划分为可无锁的操作;否则,将该操作划分为不应无锁的操作。
16.一种对数据结构的实例进行操作的系统,包括:
弱锁装置,用于为至少一可无锁的操作请求获取一第一锁的弱锁,以便对该数据结构的所述实例进行操作;
可无锁的操作执行装置,用于响应于该至少一可无锁的操作完成获取弱锁,执行该至少一可无锁的操作对该数据结构的实例进行的操作;
强锁装置,用于为一不应无锁的操作请求获取所述第一锁的强锁,以便对该数据结构的所述实例进行操作;以及
不应无锁的操作执行装置,用于响应于该不应无锁的操作完成获取该强锁,执行该不应无锁的操作对该数据结构的实例进行的操作。
17.根据权利要求16所述的系统,其中,弱锁装置和强锁装置进一步配置为:允许有多个操作同时分别持有该第一锁的多个弱锁,只允许一个操作持有该第一锁的强锁,不允许该第一锁的弱锁和强锁同时被持有;可无锁的操作执行装置进一步配置为允许持有该第一锁的弱锁的多个可无锁的操作并行执行。
18.根据权利要求17所述的系统,其中进一步包括阻塞装置,该阻塞装置配置为:响应于执行该不应无锁的操作,阻塞请求该第一锁的强锁的操作;响应于执行该不应无锁的操作,阻塞请求该第一锁的弱锁的操作或其它请求该第一锁的强锁的操作。
19.根据权利要求16所述的系统,其中所述弱锁装置进一步配置为:响应于该可无锁的操作完成对该数据结构的实例的操作,释放该弱锁;所述强锁装置进一步配置为响应于该不能无锁的操作完成对该数据结构的实例的操作,释放该强锁。
20.根据权利要求16所述的系统,其中可无锁的操作所执行的操作可以包括写操作。
21.根据权利要求16所述的系统,其中进一步包括操作划分装置,用于将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。
22.根据权利要求21所述的系统,其中操作划分装置进一步配置为使用根据方法权利要求7-15所述的方法的一种或多种,将对数据结构的一实例的操作划分为可无锁的操作和不应无锁的操作。
CN200810149826A 2008-09-27 2008-09-27 用于对数据结构的实例进行操作的方法和系统 Pending CN101685406A (zh)

Priority Applications (2)

Application Number Priority Date Filing Date Title
CN200810149826A CN101685406A (zh) 2008-09-27 2008-09-27 用于对数据结构的实例进行操作的方法和系统
PCT/EP2009/062391 WO2010034777A1 (en) 2008-09-27 2009-09-24 Method and system for parallel processing of a data structure instance

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
CN200810149826A CN101685406A (zh) 2008-09-27 2008-09-27 用于对数据结构的实例进行操作的方法和系统

Publications (1)

Publication Number Publication Date
CN101685406A true CN101685406A (zh) 2010-03-31

Family

ID=41228802

Family Applications (1)

Application Number Title Priority Date Filing Date
CN200810149826A Pending CN101685406A (zh) 2008-09-27 2008-09-27 用于对数据结构的实例进行操作的方法和系统

Country Status (2)

Country Link
CN (1) CN101685406A (zh)
WO (1) WO2010034777A1 (zh)

Cited By (6)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN103383654A (zh) * 2012-05-03 2013-11-06 百度在线网络技术(北京)有限公司 调节mapper在多核上执行的方法及装置
CN106980544A (zh) * 2017-03-31 2017-07-25 北京奇艺世纪科技有限公司 一种线程同步方法及线程同步系统
WO2018161881A1 (zh) * 2017-03-09 2018-09-13 腾讯科技(深圳)有限公司 结构化数据的处理方法、存储介质和计算机设备
CN110704198A (zh) * 2018-07-10 2020-01-17 阿里巴巴集团控股有限公司 数据操作方法、装置、存储介质以及处理器
CN111177233A (zh) * 2018-11-09 2020-05-19 商派软件有限公司 一种cas库存控制方法
CN113767372A (zh) * 2019-05-09 2021-12-07 国际商业机器公司 执行多核处理器的多个数据请求

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US8484235B2 (en) 2011-03-28 2013-07-09 International Business Machines Corporation Dynamically switching the serialization method of a data structure

Cited By (9)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN103383654A (zh) * 2012-05-03 2013-11-06 百度在线网络技术(北京)有限公司 调节mapper在多核上执行的方法及装置
CN103383654B (zh) * 2012-05-03 2017-03-15 百度在线网络技术(北京)有限公司 调节mapper在多核上执行的方法及装置
WO2018161881A1 (zh) * 2017-03-09 2018-09-13 腾讯科技(深圳)有限公司 结构化数据的处理方法、存储介质和计算机设备
CN106980544A (zh) * 2017-03-31 2017-07-25 北京奇艺世纪科技有限公司 一种线程同步方法及线程同步系统
CN106980544B (zh) * 2017-03-31 2020-03-03 北京奇艺世纪科技有限公司 一种线程同步方法及线程同步系统
CN110704198A (zh) * 2018-07-10 2020-01-17 阿里巴巴集团控股有限公司 数据操作方法、装置、存储介质以及处理器
CN110704198B (zh) * 2018-07-10 2023-05-02 阿里巴巴集团控股有限公司 数据操作方法、装置、存储介质以及处理器
CN111177233A (zh) * 2018-11-09 2020-05-19 商派软件有限公司 一种cas库存控制方法
CN113767372A (zh) * 2019-05-09 2021-12-07 国际商业机器公司 执行多核处理器的多个数据请求

Also Published As

Publication number Publication date
WO2010034777A1 (en) 2010-04-01

Similar Documents

Publication Publication Date Title
US7975271B2 (en) System and method for dynamically determining a portion of a resource for which a thread is to obtain a lock
US7797704B2 (en) System and method for performing work by one of plural threads using a lockable resource
CN101685406A (zh) 用于对数据结构的实例进行操作的方法和系统
US8375175B2 (en) Fast and efficient reacquisition of locks for transactional memory systems
US8145817B2 (en) Reader/writer lock with reduced cache contention
US8250047B2 (en) Hybrid multi-threaded access to data structures using hazard pointers for reads and locks for updates
AU2016244128B2 (en) Processing database transactions in a distributed computing system
Wang et al. Scaling multicore databases via constrained parallel execution
US20100023946A1 (en) User-level read-copy update that does not require disabling preemption or signal handling
US20070157200A1 (en) System and method for generating a lock-free dual queue
DE102009012766A1 (de) Ein Zugriffssperrenvorgang, um atomare Aktualisierungen zu einem geteilten Speicher zu ermöglichen
DE112012002465T5 (de) Grafikprozessor mit nicht blockierender gleichzeitiger Architektur
CN106716348A (zh) 用于执行多个线程的数据处理设备中的共享资源
US10360079B2 (en) Architecture and services supporting reconfigurable synchronization in a multiprocessing system
Sharma et al. A competitive analysis for balanced transactional memory workloads
Michael et al. Relative performance of preemption-safe locking and non-blocking synchronization on multiprogrammed shared memory multiprocessors
US20090235273A1 (en) Future scheduling by direct representation of possible dependencies
US20190079807A1 (en) Scalable spinlocks for non-uniform memory access
CN112346879B (zh) 进程管理方法、装置、计算机设备及存储介质
Bueso et al. An overview of kernel lock improvements
Gustedt et al. Relaxed synchronization with ordered read-write locks
Choi Formal Verification of Chase-Lev Deque in Concurrent Separation Logic
US20060156305A1 (en) Multiple task access to an ordered data structure
Horie et al. Balanced double queues for GC work-stealing on weak memory models
Vee et al. Meeting challenges of container port operations for the next millennium

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C02 Deemed withdrawal of patent application after publication (patent law 2001)
WD01 Invention patent application deemed withdrawn after publication

Application publication date: 20100331