gpt4 book ai didi

multithreading - 当函数具有互斥锁时,为什么要使它递归?

转载 作者:行者123 更新时间:2023-12-03 13:21:17 24 4
gpt4 key购买 nike

https://stackoverflow.com/a/5524120/462608

If you want to call functions recursively, which lock the same mutex, then they either have to use one recursive mutex, or
have to unlock and lock the same non-recursive mutex again and again (beware of concurrent threads!), or
have to somehow annotate which mutexes they already locked (simulating recursive ownership/mutexes).



在任何情况下,这是否可以使已具有互斥锁的函数递归成为“明智的”设计决策?

最佳答案

除了paxdiablo使用实际的递归函数之外,不要忘了递归使用互斥锁并不一定意味着所涉及的函数是递归的。我发现递归互斥锁可用于处理以下情况:您需要对某些数据结构进行原子操作的复杂操作,而这些复杂操作依赖于更基本的操作,因为基本操作仍然需要使用互斥锁也可以单独使用。一个示例可能类似于以下内容(请注意,该代码仅是说明性的-它未使用在处理帐户和日志时可能确实需要的适当的错误处理或事务处理技术):

struct account
{
mutex mux;

int balance;

// other important stuff...

FILE* transaction_log;
};

void write_timestamp( FILE*);


// "fundamental" operation to write to transaction log
void log_info( struct account* account, char* logmsg)
{
mutex_acquire( &account->mux);

write_timestamp( account->transaction_log);
fputs( logmsg, account->transaction_log);

mutex_release( &account->mux);
}


// "composed" operation that uses the fundamental operation.
// This relies on the mutex being recursive
void update_balance( struct account* account, int amount)
{
mutex_acquire( &account->mux);

int new_balance = account->balance + amount;

char msg[MAX_MSG_LEN];
snprintf( msg, sizeof(msg), "update_balance: %d, %d, %d", account->balance, amount, new_balance);

// the following call will acquire the mutex recursively
log_info( account, msg);

account->balance = new_balance;

mutex_release( &account->mux);
}

在不使用递归互斥量的情况下执行或多或少等效的操作意味着代码将需要注意不要重新获取互斥量(如果已保存)。一种选择是在数据结构中添加某种标志(或线程ID),以指示互斥体是否已被保留。在这种情况下,您实际上是在实现递归互斥体-比起初看起来正确时要复杂得多的工作。一种替代方法是传递一个标志,指示您已经获取了互斥锁以用作参数(更容易实现和正确使用),或者只是具有甚至更基本的操作(假设已经获取了互斥锁),并从更高级别的函数中调用该互斥锁。获得互斥体的责任:
// "fundamental" operation to write to transaction log
// this version assumes that the lock is already held
static
void log_info_nolock( struct account* account, char* log msg)
{
write_timestamp( account->transaction_log);
fputs( logmsg, account->transaction_log);
}


// "public" version of the log_info() function that
// acquires the mutex
void log_info( struct account* account, char* logmsg)
{
mutex_acquire( &account->mux);
log_info_nolock( account, logmsg);
mutex_release( &account->mux);
}


// "composed operation that uses the fundamental operation
// since this function acquires the mutex, it much call the
// "nolock" version of the log_info() function
void update_balance( int amount)
{
mutex_acquire( &account->mux);

int new_balance = account->balance + amount;

char msg[MAX_MSG_LEN];
snprintf( msg, sizeof(msg), "update_balance: %d, %d, %d", account->balance, amount, new_balance);

// the following call assumes the lock is already acquired
log_info_nolock( account, msg);

account->balance = new_balance;

mutex_release( &account->mux);
}

关于multithreading - 当函数具有互斥锁时,为什么要使它递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10546867/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com