使用简单两相锁定的并发程序

concurrent program using simple two phase locking

本文关键字:并发 程序 锁定 简单      更新时间:2023-10-16

>问题:我想使用所谓的两相锁定概念并发计算一些方程。

我的方法是:创建一个数组,该数组将实时更新每个变量的值。我有点卡在我应该创建线程的方式上,在算法上应用互斥/信号量以并发进行。

输入(当然,我将构建一组更大的方程来测试并发程序的效率(

2
3 6
&0 = &0 + 4 + 3
&1 = &0 - &1 + 2 + 5
&0 = &1 + 3

输入说明:

第一行是未知数。(&0 和 &1 是未知数( 第二行是它们各自的初始值。(&0 等于 3,&1 等于 6( 接下来的几行是方程式。

输出

&0 = 14
&1 = 11

在我实现方程的结构下方(可以吗?可以改进吗?

struct X{
int id; // the calculated variable
int sum; // the sum of every constants
std::string eq; // the row as a string
std::unordered_map<int, int> unknowns; // store all the unknowns and counts them
X(std::string);
void parsing(); // parse eq to get id, sum and unknowns
void updating(); // update the value of id on a global array when all the unknowns are available
};

1. 在赋值之间构建依赖关系图

我认为您的目标是并行计算尽可能多的赋值,同时获得与依次计算作业相同的结果。为了确定可以并行完成的操作,我建议在赋值表达式之间构建一个依赖关系图。

从上一个赋值开始:任何参与赋值的变量都意味着要计算它,我们需要计算对所涉及的变量进行修改的最后一个赋值。使用您给出的示例:

&0 = 3                // A0 (variable initialization)
&1 = 6                // A1 (variable initialization)
&0 = &0 + 4 + 3       // A2
&1 = &0 - &1 + 2 + 5  // A3
&0 = &1 + 3           // A4

依赖关系包括:

A4 <-- A3         (To compute A4, you need to compute A3 before)
A3 <-- A2 and A1  (To compute A3, you need to compute A2 for the value of &0 and A1 for &1)
A2 <-- A0
A1 <-- no dependency
A0 <-- no dependency

2. 递归计算依赖关系

免责声明:我对C++中锁和螺纹的使用不是很熟悉。但我想我可以给出一个一般的方法。

现在,您已经确定了依赖项是什么,您可以尝试计算它们。我可以为线程的过程建议这种简单的方法:

computeAssignment(Assignment * as) {
if (as is not computed) {
lock Assignment as
for each dependency of as {
spawn a thread running computeAssignment(dependency) // Recursion occurs here
}
wait for all the threads spawned in the for loop to finish
compute the result of this assignment
unlock Assignment as
}
return result of as
}

当线程开始检查它被赋予的赋值时,它首先检查它之前是否被计算过。如果未计算赋值,则执行此检查的方式必须使第一个进行此检查的线程阻止对所有其他线程的访问。

当第一个线程忙于生成线程以计算依赖项和计算赋值结果时,其他线程在第一次检查中被阻止。当第一个线程最终解锁分配时,所有等待的线程都将看到结果已计算。

要开始计算,您应该为您拥有的每个变量生成其中一个线程,并为他们提供最后一个将变量修改为参数的赋值。在您的示例中,这将是 2 个线程,从赋值 A4(最后修改 &0(和 A3(最后修改 &1(开始。