【发布时间】:2019-09-01 14:38:19
【问题描述】:
假设我们有整体对象关系。例如,有一个Boss 可以拥有多个Workers。
对于Boss,我们需要以下操作:
- 将新的
Worker添加到其“集合”中 - 将现有的
Worker对象转移到另一个Boss对象
我在下面提供了一些 C++ 代码来说明这个想法(跳过了一些函数)。
class Worker {
private:
Boss *owner = nullptr;
std::string name;
public:
Worker(std::string name) : name(name), owner(nullptr) { }
Boss* getOwner() const {
return this->owner;
}
void setOwner(Boss *owner) {
this->owner = owner;
}
};
class Boss {
private:
std::set<Worker *> workers;
std::string name;
public:
Boss(std::string name) : name(name) { }
~Boss() {
for (auto worker : this->workers) {
delete worker;
}
this->workers.clear();
}
void addWorker(Worker *worker) {
this->workers.emplace(worker);
worker->setOwner(this);
}
void transferOwnership(Worker *dummyWorker, Boss *newOwner);
};
int main()
{
Boss b1{ "boss1" };
Boss b2{ "boss2" };
b1.addWorker(new Worker{ "w1" });
b1.addWorker(new Worker{ "w2" });
b2.addWorker(new Worker{ "w3" });
Worker temp{ "w2" };
b1.transferOwnership(&temp, &b2);
b1.print(); // boss: boss1 having workers: w1
b2.print(); // boss: boss2 having workers: w2 w3
return 0;
}
transferOwnership() 函数的串行实现如下:
void Boss::transferOwnership(Worker *dummyWorker, Boss *newOwner) {
// find existing worker
Worker *actualWorker = nullptr;
for (auto worker : this->workers) {
if (*worker == *dummyWorker) {
actualWorker = worker;
}
}
if (nullptr == actualWorker) {
return;
}
// remove existing worker from this
this->workers.erase(actualWorker);
// add worker to other (newOwner)
newOwner->workers.emplace(actualWorker);
actualWorker->setOwner(newOwner);
}
现在,我们想要并行化这个场景。假设有多个线程可以对任何现有的Boss 对象执行任何可用操作(addWorker() 或transferOwnership())。
问题是如何同步代码,这样我们最后总能得到一致的结果,而不会陷入死锁。
我认为一个解决方案是在Boss 类中添加一个静态互斥变量,在操作开始时将其锁定并在操作结束时结束。这将保护所有 Boss 对象的所有 workers 集。
另一种解决方案是为每个Boss 对象设置一个互斥锁。但是,我认为在这里我们可能会遇到死锁,就像在 transferOwnership() 中一样,我们需要锁定/解锁 Bosses 的互斥锁,我认为在这种情况下我们不能强加特定的锁定顺序。
你能想到其他/更好的解决方案吗?
【问题讨论】:
-
您已在问题的最后两段中回答了您自己的问题。那么,你到底在问什么?
-
你的意思是stackoverflow.com/q/5429653/6296561 之类的吗?
标签: c++ oop synchronization