2011-12-08 40 views
2

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

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中创建的帐户列表?现在,无论什么时候我从客户端拉出帐户列表,都会对线程进行更改,但在连接后,我看不到主要帐户列表中的更改。同样,我认为它与我在Client对象或主要或可能的RunTransactions中传递或访问帐户的方式有关?任何意见将不胜感激!

+1

与你的问题无关,但你为什么避免使用' - >'运算符? –

回答

1
Client::Client(list<Transaction> a, list<Account> b) { 

b是被传入的列表的副本,几乎肯定会传递到堆栈上。只要构造函数返回,您的指针可能无效。

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

+0

不确定你的意思是“使帐户成为实际列表”。如果我只是把它作为一个列表而不是一个指向Client类的指针,它不会只是一个副本,所以所有的改变都不会影响main中的列表吗? –

+0

对。这些副作用通常是一种意外 - 即使不是,他们也是一个坏主意。 (它被称为“远处的行动”,它是一种反模式)。如果你想在你的客户端做了一些事情之后得到列表,那么在客户端添加方法来获取列表。一般来说,你的对象应该拥有它里面的任何东西;否则,调用者可以使用该对象的内部状态并打破您指定的任何不变量。 – cHao

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

基本上是说:“噢,罗伊,你在这里有这个列表中,右键,所有的这些客户,有人通过电子邮件发送给我,你可以看到,该列表与,只是店里来了?谁创建了这个列表的名字?我确信我们以后可以从这个地址获取列表。“

因此罗伊在客户的个人资料中存储“沃尔多”这个名字。我们都知道之后发生了什么。可悲的是,当客户要求时,他再也找不到名单了。如果他只是制作了一份清单的副本,或者确保创建清单的来源有一天不会消失。