【问题标题】:Global List Access Using PThreads - Pointer Issue?使用 PThreads 访问全局列表 - 指针问题?
【发布时间】:2011-12-08 16:12:22
【问题描述】:

我们正在做一个项目,使用线程和互斥锁来模拟一群客户访问不同或相同的银行账户。我几乎没有 C/C++ 经验,我认为这个问题与指针有关。基本上,我有一个 Client 对象,其中包含一个交易列表和一个帐户列表,并作为参数传递给 pthread,然后将其发送到处理方法。

class Client{
public:
    list<Transaction> transactions;
    list<Account>* accounts;
    Client(list<Transaction>, list<Account>);
};

Client::Client(list<Transaction> a, list<Account> b){
transactions = a;
accounts = &b;
}

extern "C"
{
void* RunTransactions(void* arg)
{
    Client* c = static_cast<Client*>(arg);

    // while(!(*c).transactions.empty()){
        // cout << "HERE" << endl;
    // }

    cout << "Thread Before: ";
    (*(*c).accounts).front().Print();

    (*(*c).accounts).front().balance -= 25;
    (*(*c).accounts).front().balance -= 25;
    (*(*c).accounts).front().balance -= 25;

    cout << "Thread After: ";
    (*(*c).accounts).front().Print();

    // list<Transaction>* trans = static_cast<list<Transaction>*>(arg);
    // Transaction t = trans->front();
    // t.Print();

    // Test* t = static_cast<Test*>(arg);

    // (*t).Increase();
    // cout << "Thread - " << t->x << endl;

    return 0;
}
}

int main( ){

list<Account> accounts;

cout << "Accounts: ";
cin >> NumAccts;

for(long i = 0; i < NumAccts; i++){
    long tempBalance;
    cout << "Balance for Account " << i << ": ";
    cin >> tempBalance;

    accounts.push_back(Account(i, tempBalance));
}

//Test Input
pthread_t t1;
list<Transaction> tempTrans;
tempTrans.push_back(Transaction(0, 1, 100));
tempTrans.push_back(Transaction(1, 0, 50));
tempTrans.push_back(Transaction(2, 1, 222));

Client c = Client(tempTrans, accounts);

cout << "Main Before: ";
accounts.front().Print();

pthread_create(&t1, NULL, RunTransactions, &c);

pthread_join(t1, NULL);

cout << "Main After: ";
accounts.front().Print();


return 0;
}

我不明白我应该如何让我的线程都可以访问在 main 中创建的帐户列表?现在,每当我对从客户端中拉出的帐户列表进行任何操作时,它都会在线程中进行更改,但是在加入后我看不到 main 中的帐户列表中的更改。同样,我认为这与我在 Client 对象或 main 中传递或访问帐户的方式有关,或者可能与 RunTransactions 有关?任何建议将不胜感激!

【问题讨论】:

  • 与您的问题无关,但您为什么要避免使用 -&gt; 运算符?

标签: c++ c pointers pthreads


【解决方案1】:
Client::Client(list<Transaction> a, list<Account> b) {

b 是传入列表的副本,几乎肯定会在堆栈上传递。一旦构造函数返回,你的指针可能是无效的。

最好将客户的accounts 设为实际列表,而不是指向列表的指针。你真的不想让你的对象持有一个指向不是堆分配的东西的指针,或者其他人可以访问的东西。那就是疯狂。

【讨论】:

  • 不确定您所说的“使帐户成为实际列表”是什么意思。如果我只是把它做成一个列表而不是 Client 类中的一个指针,它不还是只是一个副本,所以所有的更改都不会影响 main 中的列表吗?
  • 对。这些副作用通常是偶然的——即使不是,它们也是一个坏主意。 (它被称为“远距离动作”,它是一种反模式。)如果您在客户端完成某些操作后想要列表,则在客户端上添加方法以获取列表。一般来说,你的对象应该拥有它里面的任何东西。否则,调用者可能会弄乱对象的内部状态并破坏您指定的任何不变量。
【解决方案2】:
Client::Client(list<Transaction> a, list<Account> b){
    transactions = a;
    accounts = &b;
}

基本上是在说:“哦,是的,Roy,你有这个列表,对吧,所有这些帐户?嗯,有人通过电子邮件发送给我,你能看到那个列表来自哪里,并存储谁的名字创建了列表?我相信我们以后可以从该地址取回列表。”

因此,Roy 将名称“Waldo”存储在客户的个人资料中。我们都知道那之后发生了什么。可悲的是,当客户要求时,他再也无法检索到该列表。要是他复制了一份清单,或者确保创建清单的来源不会在某一天消失就好了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-13
    • 2014-07-21
    • 1970-01-01
    • 2019-06-07
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多