多线程二进制树算法
Multi-Threaded Binary Tree Algorithm
所以我尝试了一种方法,在查看每个节点时锁定它,但这需要锁定和解锁的ALOT。。。这当然需要相当多的开销。我想知道是否有人知道一种更有效的算法。这是我的第一次尝试:
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);
}
}
您不需要锁定您访问的每个节点。你可以这样做。在即将执行插入操作时锁定节点。插入并解锁。如果另一个线程碰巧需要在同一点插入它,并且节点被锁定,那么它应该等待,然后再向下遍历。一旦节点被解锁,它就可以继续遍历树的更新部分。
另一种简单的方法是为整个树设置1个锁。
您可以对树进行更序列化的访问,但您只有一个互斥对象,并且只锁定一次。如果序列化是一个问题,则使用读/写锁。因此至少可以并行地进行读取。
使用读写锁。如果您以后决定切换树实现,那么锁定单个节点将变得异常困难。下面是一个使用pthreads的小演示代码:
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
}
锁定整个树。没有其他方法不会让你迟早陷入麻烦。当然,如果有大量的并发读写,你会遇到大量的阻塞,并使一切都慢下来。
Java在1.6版本中引入了一个并发跳过列表。跳过列表像树一样工作,但(据说)有点慢。然而,它们基于单链表,因此理论上可以使用比较和交换在不锁定的情况下进行修改。这使得多线程性能卓越。
我在谷歌上搜索了"跳过列表"C++比较和交换,得到了一些有趣的信息,但没有C++代码。然而,Java是开源的,所以如果你足够绝望的话,你可以得到算法。Java类是:Java.util.concurrent.CurrentSkipListMap.
相关文章:
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 为什么这个运算符<重载函数对 STL 算法不可见?
- 有根的二进制搜索树.保留与其父级的链接
- 多态二进制函数
- 基于ELO的团队匹配算法
- C++选择排序算法中的逻辑错误
- 有没有办法将谓词中的元素偏移量传递给 std 算法?
- C++A*算法并不总是在路径中具有目标节点
- 了解一种神秘地起作用的递归二进制搜索算法
- 二进制树数算法不起作用
- C++正在创建二进制搜索树:EXC_BAD_ACCESS错误.算法错误还是编码错误
- 二进制加法算法
- 二进制 GCD - 算法太慢
- 二进制搜索答案算法
- 在遗传算法中使用二进制编码是必要的吗
- 以从 a 到 b 的数字的二进制表示形式计算 "1" 位数字的算法
- 二进制搜索树最佳拟合算法:输出不正确
- 将算法c++的无效操作数替换为二进制表达式
- 多线程二进制树算法
- 为什么自制的二进制搜索算法比std::binary_search慢