多线程通过数组处理数据的方法、系统及多线程处理器
技术领域
本发明涉及数据处理领域,特别是一种多线程通过数组处理数据的方法、系统及多线程处理器。
背景技术
随着CPU内核数量的不断增加,多线程开发应用已经是不可或缺的重要软件技术,利用多线程并发执行机制可显著提升软件的运行效率。当前,在多个线程之间进行数据存取和交换操作时,普遍采用的是互斥锁的方式进行处理,一个线程在存储数据时需要加锁,另一个线程在读取数据时也需要加锁,这种方式保障了多个线程之间数据存取和交换的安全性,但也增加了软件运行的开销和编程难度。互斥锁将使软件运行进入内核模式,从而影响了软件运行的流畅性和高效性,且互斥锁使用不当很容易造成死锁等困扰。因此,在实际的应用中,如何规避互斥锁的使用,从而避免软件进入死锁状态和内核模式,是当前的一个技术性难题。
发明内容
为解决上述问题,本发明的目的在于提供一种多线程通过数组处理数据的方法、系统及多线程处理器,在不使用互斥锁的情况下,高效和安全的保障数据存取和交换过程,避免死锁状态和进入内核运行模式。
本发明解决其问题所采用的技术方案是:
一种多线程通过数组处理数据的方法,所述数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,且所述数组设置有存储计数和与存储计数对应的两个游标,所述存储计数用于标记数组中存储的元素个数,所述两个游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置,所述方法包括存储的步骤:
(11)判断存储计数与数组可存储元素个数的大小;
(12)当存储计数小于数组可存储元素个数时,存储计数加1,且将扩展存储游标加1使其移动至当前线程进行存储的元素位置,并执行步骤(3),否则,结束存储;
(13)将存储后的元素的状态值标记为已存储;
(14)循环执行步骤(12)和步骤(13),直至所有线程存储完相应的数据;
(15)依次检测存储游标至扩展存储游标之间所有元素的状态值,若元素的状态值标记为已存储,则将存储游标加1,否则,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述数组还设置有读取计数,所述读取计数用于标记数组中可读取的元素个数,在所述步骤(15)中,依次检测存储游标至扩展存储游标之间所有元素的状态值时,若元素的状态值标记为已存储,则将存储游标的值备份后通过原子交换函数将存储游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将读取计数加1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述数组还设置有与读取计数对应的另外两个游标,分别为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置,所述方法还包括读取的步骤:
(31)判断读取计数是否大于0;
(32)若读取计数大于0时,读取计数减1,且将扩展读取游标加1使其移动至当前线程进行读取的元素位置,并执行步骤(33),否则,结束读取;
(33)将读取后的元素的状态值标记为未存储;
(34)循环执行步骤(32)与步骤(33),直至所有线程读取完相应的数据;
(35)依次检测读取游标至扩展读取游标之间所有元素的状态值,若元素的状态值标记为未存储,则将读取游标的值备份后通过原子交换函数将读取游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将存储计数减1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为已存储,当前线程结束检测并返回。
所述数组的大小为2的N次方,所述存储游标、扩展存储游标、读取游标、扩展读取游标在移动时,其游标值通过与数组大小进行取余操作指示相应元素的位置。
所述状态值用0标记未存储,用1标记已存储。
一种多线程通过数组处理数据的系统,所述所述数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,且所述数组设置有存储计数和与存储计数对应的两个游标,所述存储计数用于标记数组中存储的元素个数,所述两个游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置,所述系统包括存储模块,所述存储模块包括:
存储判断单元,判断存储计数与数组可存储元素个数的大小;
存储移动单元,当存储计数小于数组可存储元素个数时,存储计数加1,且将扩展存储游标加1使其移动至当前线程进行存储的元素位置,并转移至存储标记单元执行相应命令,否则,结束存储;
存储标记单元,将存储后的元素的状态值标记为已存储;
存储循环单元,存储移动单元与存储标记单元依次循环执行,直至所有线程存储完相应的数据;
存储检测单元,依次检测存储游标至扩展存储游标之间所有元素的状态值,若元素的状态值标记为已存储,则将存储游标加1,否则,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述数组还设置有读取计数,所述读取计数用于标记数组中可读取的元素个数,在所述存储检测单元依次检测存储游标至扩展存储游标之间所有元素的状态值时,若元素的状态值标记为已存储,则将存储游标的值备份后通过原子交换函数将存储游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将读取计数加1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述数组还设置有与读取计数对应的另外两个游标,分别为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置,所述系统还包括读取模块,所述读取模块包括:
读取判断单元,判断读取计数是否大于0;
读取移动单元,若读取计数大于0时,读取计数减1,且将扩展读取游标加1使其移动至当前线程进行读取的元素位置,并转移至读取标记单元执行相应命令,否则,结束读取;
读取标记单元,将读取后的元素的状态值标记为未存储;
读取循环单元,读取移动单元与读取标记单元依次循环执行,直至所有线程读取完相应的数据;
读取检测单元,依次检测读取游标至扩展读取游标之间所有元素的状态值,若元素的状态值标记为未存储,则将读取游标的值备份后通过原子交换函数将读取游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将存储计数减1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为已存储,当前线程结束检测并返回。
所述数组的大小为2的N次方,所述存储游标、扩展存储游标、读取游标、扩展读取游标在移动时,其游标值通过与数组大小进行取余操作指示相应元素的位置。
一种多线程处理器,所述处理器包括:
存储器,存储有一维数组,所述数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,且所述数组设置有存储计数和与存储计数对应的两个游标,所述存储计数用于标记数组中存储的元素个数,所述两个游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置,所述数组还设置有读取计数和与读取计数对应的另外两个游标,所述读取计数用于标记数组中可读取的元素个数,所述另外两个游标分别为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置;
存储装置,用于通过数组存储多线程需要存储的数据;
读取装置,用于通过数组读取多线程需要读取的数据。
所述存储装置包括:
存储判断模块,判断存储计数与数组可存储元素个数的大小;
存储移动模块,当存储计数小于数组可存储元素个数时,存储计数加1,且将扩展存储游标加1使其移动至当前线程进行存储的元素位置,并转移至存储标记模块执行相应命令,否则,结束存储;
存储标记模块,将存储后的元素的状态值标记为已存储;
存储循环模块,存储移动单元与存储标记单元依次循环执行,直至所有线程存储完相应的数据;
存储检测模块,依次检测存储游标至扩展存储游标之间所有元素的状态值,若元素的状态值标记为已存储,则将存储游标的值备份后通过原子交换函数将存储游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将读取计数加1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述读取装置包括:
读取判断模块,判断读取计数是否大于0;
读取移动模块,若读取计数大于0时,读取计数减1,且将扩展读取游标加1使其移动至当前线程进行读取的元素位置,并转移至读取标记模块执行相应命令,否则,结束读取;
读取标记模块,将读取后的元素的状态值标记为未存储;
读取循环模块,读取移动模块与读取标记模块依次循环执行,直至所有线程读取完相应的数据;
读取检测模块,依次检测读取游标至扩展读取游标之间所有元素的状态值,若元素的状态值标记为未存储,则将读取游标的值备份后通过原子交换函数将读取游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将存储计数减1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为已存储,当前线程结束检测并返回。
本发明的有益效果是:
本发明采用一种多线程通过数组处理数据的方法、系统及多线程处理器,多线程以数组的方式存储与读取数据,避免互斥锁的使用,提升存储与读取的效率;游标以原子递增的方式,使多个线程同时存取数据的位置不重叠,保证多个线程并行运行且互不干扰;数组的大小设定为2的N次方,简化游标的操作为原子递增,即使游标范围溢出从0开始,仍能保证正确的位置指向;为内核设计、多线程设计和服务器并发设计等提供了新的设计思路。
附图说明
下面结合附图和实例对本发明作进一步说明。
图1是所述数组的结构示意图;
图2是所述方法中存储步骤的流程图;
图3是所述方法中读取步骤的流程图;
图4是所述系统中存储模块的结构组成框图;
图5是所述系统中读取模块的结构组成框图;
图6是所述处理器的结构组成框图;
图7是所述存储装置的结构组成框图;
图8是所述读取装置的结构组成框图;
图9是4个线程存储时数组变化的示意图;
图10是4个线程中部分线程存储后数组变化的示意图;
图11是4个线程全部存储后数组变化的示意图;
图12是4个线程读取时数组变化的示意图;
图13是4个线程中部分线程读取后数组变化的示意图;
图14是4个线程全部读取后数组变化的示意图。
具体实施方式
实施例1:
参照图1所示,本发明构建了一种数组,数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,其中,状态值以0表示未存储数据,以1表示已存储数据;数组设置了两个存储计数和读取计数,存储计数用于标记数组中存储的元素个数,读取计数用于标记数组中可读取的元素个数;数组分别对应存储计数和读取计数设置有两组游标,对应存储计数的游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置,对应读取计数的游标为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置。
如图1中所示,在初始化时,数组中没有存储元素,所有元素的状态值均为0,存储计数与读取计数均为0,四个游标的值均设定为-1,以方便后续的使用。
参照图2所示,当多个线程需要同时存储数据时,具体的步骤如下:
步骤200,首先要检查数组是否有空位,即判断存储计数与数组可存储元素个数的大小;
步骤202,若存储计数小于数组可存储元素个数,则存储计数加1,且将扩展存储游标加1使扩展存储游标移动至当前线程进行存储的元素位置,并执行步骤204,否则,说明数组没有存储空间,线程直接返回,并结束存储,因为存储计数的最大值只能是数组的大小,因此,存储计数小于或等于数组大小,小于时,说明有存储空间,等于时即没有存储空间;
步骤204,当线程将某个元素存储完成后,即将此存储后的元素的状态值标记为已存储,即设置为1,线程会一直循环步骤202与步骤204,直至存储完相应的数据;
步骤206,存储完毕后,需要依次检测存储游标至扩展存储游标之间所有元素的状态值时;
步骤208,若元素的状态值标记为已存储,即状态值为1,则将存储游标的值备份后通过原子交换函数将存储游标的值加1;
步骤210,比较原子交换函数返回的值与所述备份值;
步骤212,如果两个值相等,说明当前线程操作成功,则将读取计数加1,并循环步骤206,依次检测下一个元素,否则,说明有其他线程在进行检测,并且其他线程已经设置了存储游标的值,当前线程则结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
整个存储过程,只通过数组即可完成,且允许多个线程同时存储,避免现有技术中互斥现象的发生,且提高了存储效率。
参照图3所示,当一个或多个线程需要读取数据时,具体如下:
步骤300,首先要检查数组是否有可读取元素,即判断读取计数是否大于0;
步骤302,如果读取计数大于0,说明有可读取的元素,将读取计数减1,且将扩展读取游标加1使扩展读取游标移动至当前线程进行读取的元素位置,并执行步骤304,如果读取计数等于0,说明没有可读取的元素,当前线程直接结束读取操作;
步骤304,当前线程读取完某个元素后,则将此元素的状态值标记为未存储,即设置为0,线程则循环步骤302与步骤304,直至读取完相应的数据;
步骤306,读取完毕后,依次检测读取游标至扩展读取游标之间所有元素的状态值;
步骤308,若元素的状态值标记为未存储,即状态值为0,则将读取游标的值备份后通过原子交换函数将读取游标的值加1;
步骤310,比较原子交换函数返回的值与所述备份值;
步骤312,如果若原子交换函数返回的值与所述备份值相等,说明当前线程操作成功,将存储计数减1,并循环步骤306,依次检测下一个元素,否则,说明有其他线程在进行检测,并且其他线程已经设置了读取游标的值,当前线程直接返回,若遇到的元素的状态值是已存储时,即状态值为1,说明此元素的线程还未完成读取操作,当前线程结束检测并返回。
从以上方法中可知,四个游标始终是递增向前的,数据的存储一直向前扩展,数据的读取也一直向前扩展,而数组的大小是有限的,因此在游标超过数组大小时,需要将游标重置到0重新开始。而为了不影响游标的原子操作性,实际应用中游标仍然一直递增且可以大于数组大小,当得到游标存取位置时,将其与数组的大小取余得到实际的数组位置再进行存取操作。若游标类型为无符号32位整数时(unsignedint),当递增超出整数范围时将又从0开始,因此数组的大小设计为2的N次方,保证了游标无论是否溢出,通过与数组大小取余,仍能准确的指向数组的元素。
本发明提供了一种多线程通过数组处理数据的系统,包括存储模块与读取模块,其中,存储模块的组成框图参照图4所示,读取模块的存储框图参照图5所示,存储模块与读取模块通过数组实现多个线程的存储与读取,所述所述数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,且所述数组设置有存储计数和与存储计数对应的两个游标,所述存储计数用于标记数组中存储的元素个数,所述两个游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置;所述数组还设置有读取计数和与读取计数对应的另外两个游标,所述读取计数用于标记数组中可读取的元素个数,所述另外两个游标分别为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置。
参照图4所示,所述存储模块包括:
存储判断单元,判断存储计数与数组可存储元素个数的大小;
存储移动单元,当存储计数小于数组可存储元素个数时,存储计数加1,且将扩展存储游标加1使其移动至当前线程进行存储的元素位置,并转移至存储标记单元执行相应命令,否则,结束存储;
存储标记单元,将存储后的元素的状态值标记为已存储;
存储循环单元,存储移动单元与存储标记单元依次循环执行,直至所有线程存储完相应的数据;
存储检测单元,依次检测存储游标至扩展存储游标之间所有元素的状态值时,若元素的状态值标记为已存储,则将存储游标的值备份后通过原子交换函数将存储游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将读取计数加1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
参照图5所示,所述读取模块包括:
读取判断单元,判断读取计数是否大于0;
读取移动单元,若读取计数大于0时,读取计数减1,且将扩展读取游标加1使其移动至当前线程进行读取的元素位置,并转移至读取标记单元执行相应命令,否则,结束读取;
读取标记单元,将读取后的元素的状态值标记为未存储;
读取循环单元,读取移动单元与读取标记单元依次循环执行,直至所有线程读取完相应的数据;
读取检测单元,依次检测读取游标至扩展读取游标之间所有元素的状态值,若元素的状态值标记为未存储,则将读取游标的值备份后通过原子交换函数将读取游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将存储计数减1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为已存储,当前线程结束检测并返回。
所述数组的大小为2的N次方,所述存储游标、扩展存储游标、读取游标、扩展读取游标在移动时,其游标值通过与数组大小进行取余操作指示相应元素的位置。
本发明还提供了一种多线程处理器,参照图6所示,包括存储器、存储装置和读取装置。
所述存储器存储有一维数组,所述数组中的每一个元素包括数据和用于标志此元素是否存储有数据的状态值,且所述数组设置有存储计数和与存储计数对应的两个游标,所述存储计数用于标记数组中存储的元素个数,所述两个游标为存储游标和扩展存储游标,所述存储游标用于指示当前数组已存储的元素位置,所述扩展存储游标用于指示当前数组正在存储的元素位置,所述数组还设置有读取计数和与读取计数对应的另外两个游标,所述读取计数用于标记数组中可读取的元素个数,所述另外两个游标分别为读取游标和扩展读取游标,所述读取游标用于指示当前数组已读取的元素位置,所述扩展读取游标用于指示当前数组正在读取的元素位置。
所述存储装置用于通过数组存储多线程需要存储的数据,参照图7所示,存储装置包括:
存储判断模块,判断存储计数与数组可存储元素个数的大小;
存储移动模块,当存储计数小于数组可存储元素个数时,存储计数加1,且将扩展存储游标加1使其移动至当前线程进行存储的元素位置,并转移至存储标记模块执行相应命令,否则,结束存储;
存储标记模块,将存储后的元素的状态值标记为已存储;
存储循环模块,存储移动单元与存储标记单元依次循环执行,直至所有线程存储完相应的数据;
存储检测模块,依次检测存储游标至扩展存储游标之间所有元素的状态值,若元素的状态值标记为已存储,则将存储游标的值备份后通过原子交换函数将存储游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将读取计数加1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为未存储,当前线程结束检测并返回。
所述读取装置用于通过数组读取多线程需要读取的数据,参照图8所示,读取装置包括:
读取判断模块,判断读取计数是否大于0;
读取移动模块,若读取计数大于0时,读取计数减1,且将扩展读取游标加1使其移动至当前线程进行读取的元素位置,并转移至读取标记模块执行相应命令,否则,结束读取;
读取标记模块,将读取后的元素的状态值标记为未存储;
读取循环模块,读取移动模块与读取标记模块依次循环执行,直至所有线程读取完相应的数据;
读取检测模块,依次检测读取游标至扩展读取游标之间所有元素的状态值,若元素的状态值标记为未存储,则将读取游标的值备份后通过原子交换函数将读取游标的值加1,同时,若原子交换函数返回的值与所述备份值相等,则将存储计数减1,并检测下一个元素,否则,当前线程结束检测并返回,若元素的状态值标记为已存储,当前线程结束检测并返回。
实施例2:
本实施例通过具体的例子对本发明作进一步详细说明。
其中,图1中所示的数组为初始化后的数据,存储游标、扩展存储游标、读取游标和扩展读取游标均为-1,存储计数和读取计数均为0。
之后,假设4个线程同时需要存储数据,参照图9中所示,各个线程所取得的存储位置如图中所示,线程2对应位置0,线程1对应位置1,线程3对应位置2,线程4对应位置3,由于4个线程都没有完成存储操作,则将存储计数置为4,读取计数仍为0,此时扩展存储游标指向位置3,存储游标仍为-1。
图10为线程2、线程3和线程4完成存储之后的示意图,虽然位置2和位置3是已存储状态,但由于线程1还未设置状态值,检测线程在将存储游标移动到位置0时退出,读取计数为1。
图11为所有线程完成存储后的示意图,即最后的线程1完成存储之后的示意图,线程1在完成存储之后,将存储游标移动到位置3,并增加读取计数为4,表明此时数组容器中有4个元素可读取。
当读取数据时,以读取图11中存储后的数据为例进行说明,此时,数组容器中已存储4个元素,且有4个元素未读取,此时读取游标和扩展读取游标均为-1。
参照图12所示,4个线程同时进行读取操作,各个线程所取得的读取位置如图中所示,线程4对应位置0,线程1对应位置1,线程2对应位置2,线程3对应位置3,由于4个线程都没有完成读取操作,存储计数仍然是4,而读取计数为0,此时扩展读取游标指向位置3,读取游标仍为-1。
图13所示为线程4和线程1完成读取之后的示意图,检测线程在遇到位置2时发现状态是已存储,说明位置2的线程还未完成读取操作,此时读取游标指向位置1,存储计数为2。
图14所示为是线程2和线程3完成读取之后的示意图,在线程2和线程3退出之后,将分别检测从位置2到位置3的状态,发现未存储状态时就将读取游标向前移动一个位置,最后与扩展读取游标一同指向位置3,存储计数为0,表明数组容器中没有存储元素也没有可读取元素。
本发明中多线程以数组的方式存储与读取数据,避免互斥锁的使用,提升存储与读取的效率;游标以原子递增的方式,使多个线程同时存取数据的位置不重叠,保证多个线程并行运行且互不干扰;数组的大小设定为2的N次方,简化游标的操作为原子递增,即使游标范围溢出从0开始,仍能保证正确的位置指向;为内核设计、多线程设计和服务器并发设计等提供了新的设计思路。
以上所述,只是本发明的较佳实施例而已,本发明并不局限于上述实施方式,只要其以相同的手段达到本发明的技术效果,都应属于本发明的保护范围。