我有一个程序,其中4个线程在两个“银行帐户”之间进行随机交易,每100个交易,每个帐户的利息为5%。
这是我必须要做的上学练习,在上一课中,我们使用了互斥锁,在锁定一段代码时看起来很简单。
现在我们必须做相同的事情,但要使用原子。
我的问题是,当前有多个线程可以输入addIntreset
函数,并且可以多次添加兴趣。
这是代码的一部分,我检查它是否是第100个事务
void transfer(Account& acc, int amount, string& thread)
{
++m_iCounter;
withdraw(acc, amount);
if (m_iCounter % 100 == 0)
{
addInterest(thread);
}
}
所有线程都通过该函数并检查%100,有时不止一个线程进入addInterest。使用互斥锁,我可以在此处限制访问权限,但是如何使用原子操作呢?也许我可以在
addInterest
中解决此问题,但如果可以,如何解决?addInterest
内部是以下代码(如果多次添加了超过1个感兴趣的线程滑动):void addInterest(string& thread)
{
float old = m_iBalance.load();
const float interest = 0.05f;
const float amount = old * interest;
while (!m_iBalance.compare_exchange_weak(old, old + amount))
{
//
}
++m_iInterest;
cout << thread << " interest : Acc" << name << " " << m_iCounter << endl;
}
最佳答案
一个问题是您分别增加和读取计数器,并且由于此addInterest
可以被多次调用。要解决此问题,您应该自动编写和阅读。
const int newCounter = ++m_iCounter;
增加兴趣:如果添加兴趣无关紧要,只要它在递增计数器后发生,那么
addInterest
可能就可以了。如果必须对第100个事务处理期间的余额增加利息(即使该线程在到达
addInterest
时已经更改),则必须以某种方式存储旧余额,然后再增加计数器。我能想到的唯一方法是通过使用原子标志代替互斥锁来同步整个transfer
:// Member variable
std::atomic_bool flag;
// Before the critical section
bool expected;
do {
expected = false;
} while (!flag.compare_exchange_weak(expected, true));
// Critical section here
// Unlock at the end
flag = false;