C++ 多线程二叉树算法

C++ 多线程二叉树算法,c++,tree,pthreads,binary-tree,C++,Tree,Pthreads,Binary Tree,所以我尝试了一种方法,可以在查看每个节点时锁定它,但这需要大量的锁定和解锁。。。这当然需要相当多的开销。我想知道是否有人知道更有效的算法。这是我的第一次尝试: typedef struct _treenode{ struct _treenode *leftNode; struct _treenode *rightNode; int32_t data; pthread_mutex_t mutex; }TreeNode; pthread_mutex_t _initMutex

所以我尝试了一种方法,可以在查看每个节点时锁定它,但这需要大量的锁定和解锁。。。这当然需要相当多的开销。我想知道是否有人知道更有效的算法。这是我的第一次尝试:

typedef struct _treenode{
   struct _treenode *leftNode;
   struct _treenode *rightNode;
   int32_t data;
   pthread_mutex_t mutex;
}TreeNode;

pthread_mutex_t _initMutex = PTHREAD_MUTEX_INITIALIZER;

int32_t insertNode(TreeNode **_trunk, int32_t data){
   TreeNode **current;
   pthread_mutex_t *parentMutex = NULL, *currentMutex = &_initMutex;

   if(_trunk != NULL){
      current = _trunk;
      while(*current != NULL){
         pthread_mutex_lock(&(*current)->mutex);
         currentMutex = &(*current)->mutex;
         if((*current)->data < data){
            if(parentMutex != NULL)
               pthread_mutex_unlock(parentMutex);
            pthreadMutex = currentMutex;
            current = &(*current)->rightNode;
         }else if((*current)->data > data){
            if(parentMutex != NULL)
               pthread_mutex_unlock(parentMutex);
            parentMutex = currentMutex;
            current = &(*current)->leftNode;
         }else{
            pthread_mutex_unlock(currentMutex);
            if(parentMutex != NULL)
               pthread_mutex_unlock(parentMutex);
            return 0;
         }
      }
      *current = malloc(sizeof(TreeNode));
      pthread_mutex_init(&(*current)->mutex, NULL);
      pthread_mutex_lock(&(*current)->mutex);
      (*current)->leftNode = NULL;
      (*current)->rightNode = NULL;
      (*current)->data = data;
      pthread_mutex_unlock(&(*current)->mutex);
      pthread_mutex_unlock(currentMutex);
   }else{
      return 1;
   }
   return 0;
}

int main(){
   int i;
   TreeNode *trunk = NULL;
   for(i=0; i<1000000; i++){
      insertNode(&trunk, rand() % 50000);
   }
}
typedef结构\u树节点{
结构树节点*左节点;
结构树节点*rightNode;
int32_t数据;
pthread_mutex_t mutex;
}三烯醇;
pthread\u mutex\u t\u initMutex=pthread\u mutex\u初始值设定项;
int32\u t插入节点(树节点**\u中继,int32\u t数据){
TreeNode**电流;
pthread_mutex_t*parentMutex=NULL,*currentMutex=&u initMutex;
如果(_trunk!=NULL){
当前=_主干;
while(*当前!=NULL){
pthread_mutex_lock(&(*current)->mutex);
currentMutex=&(*current)->mutex;
如果((*当前)->数据<数据){
if(parentMutex!=NULL)
pthread_mutex_unlock(parentMutex);
pthreadMutex=currentMutex;
当前=&(*当前)->右节点;
}else if((*当前)->数据>数据){
if(parentMutex!=NULL)
pthread_mutex_unlock(parentMutex);
parentMutex=currentMutex;
当前=&(*当前)->leftNode;
}否则{
pthread_mutex_unlock(currentMutex);
if(parentMutex!=NULL)
pthread_mutex_unlock(parentMutex);
返回0;
}
}
*电流=malloc(sizeof(TreeNode));
pthread_mutex_init(&(*current)->mutex,NULL);
pthread_mutex_lock(&(*current)->mutex);
(*当前)->leftNode=NULL;
(*当前)->rightNode=NULL;
(*当前)->数据=数据;
pthread_mutex_unlock(&(*current)->mutex);
pthread_mutex_unlock(currentMutex);
}否则{
返回1;
}
返回0;
}
int main(){
int i;
树节点*trunk=NULL;

对于(i=0;i您不需要锁定所访问的每个节点。您可以执行类似操作。在即将进行插入时锁定一个节点。执行插入并解锁。如果另一个线程恰好需要在同一点插入该节点,并且该节点被锁定,则应在进一步向下遍历之前等待。一旦该节点被解锁,则可以继续nue遍历树的更新部分。

您不需要锁定所访问的每个节点。您可以执行类似操作。在即将进行插入时锁定一个节点。执行插入并解锁。如果另一个线程恰好需要在同一点插入该节点,并且该节点已锁定,则应在进一步向下遍历之前等待。打开当节点解锁后,它可以继续遍历树的更新部分。

另一个简单的方法是为整个树设置一个锁

您可以对树进行更序列化的访问,但您只有一个互斥锁,并且只锁定一次。
如果序列化是一个问题,那么您可以使用一个。因此至少可以并行地进行读取。

另一个简单的方法是为整个树设置一个锁

您可以对树进行更序列化的访问,但您只有一个互斥锁,并且只锁定一次。
如果序列化是一个问题,您可以使用。因此至少可以并行执行读取。

使用读写锁。如果您以后决定切换树实现,锁定单个节点将变得异常困难。下面是使用以下命令的演示代码:


使用读写锁。如果以后决定切换树实现,锁定单个节点将变得异常困难。以下是使用以下方法的演示代码:


锁定整棵树。没有其他方法可以不让你早晚陷入麻烦。当然,如果有大量的并发读写,你将得到大量的阻塞,并严重降低速度

Java在1.6版中引入了并发跳过列表。跳过列表的工作方式类似于树,但(据推测)有点慢。但是,它们基于单链接列表,因此理论上可以在不使用比较和交换锁定的情况下进行修改。这有助于实现卓越的多线程性能


我在谷歌上搜索了“跳过列表”C++ C++比较和java交换是一个开源的,但是java是开源的,所以如果你够绝望的话,你可以得到算法。Java类是:java。UTI.O.CONTRONCE SKIPListMMAP.< /P> < P>锁定整个树。没有其他方法不会迟早会给你带来麻烦。当然,如果有大量的并发读写操作,你会遇到大量的阻塞,并且会大大降低速度

Java在1.6版中引入了并发跳过列表。跳过列表的工作方式类似于树,但(据推测)有点慢。但是,它们基于单链接列表,因此理论上可以在不使用比较和交换锁定的情况下进行修改。这有助于实现卓越的多线程性能


我在谷歌上搜索了“跳过列表”C++ C++比较和java交换是一个开源的,但是java是开源的,所以如果你够绝望的话,你可以得到算法。java类是:java. UTI.O.CONTRONCE。le线程“同时”执行此操作。@hexa-是的,我尝试过此操作,它看起来确实是一个强有力的选项。可能树本身有一个rwlock,而不是节点。因此,如果您只需要读取,您可以让多个线程“同时”执行此操作.@hexa-是的,我尝试过这个,它看起来确实是一个很好的选择。我在查看节点时是否不需要锁定?如果一个线程正在插入而另一个线程正在查看会怎么样?这不会导致问题吗?只要不深入到另一个线程正在插入的位置,就可以查看。这是可行的,因为插入总是发生在叶子上。在查看节点时是否不需要锁定?如果一个线程正在插入,而另一个线程正在插入,该怎么办
typedef struct {
    pthread_rwlock_t rwlock;
    TreeNode *root_node;
} Tree;

void Tree_init(Tree *tree) {
    pthread_rwlock_init(&tree->rwlock, NULL);
    tree->root_node = NULL;
}

int32_t Tree_insert(Tree *tree, int32_t data) {
    pthread_rwlock_wrlock(&tree->rwlock);
    int32_t ret = _insertNode(&tree->root_node, data);
    pthread_rwlock_unlock(&tree->rwlock);
    return ret;
}

int32_t Tree_locate(Tree *tree) {
    pthread_rwlock_rdlock(&tree->rwlock);
    int32_t ret = _locateNode(&tree->root_node);
    pthread_rwlock_unlock(&tree->rwlock);
    return ret;
}

void Tree_destroy(Tree *tree) {
    pthread_rwlock_destroy(&tree->rwlock);
    // yada yada
}