您可以使用 pthread_cleanup_push() 将取消清理处理程序推送到线程取消清理堆栈上。该处理程序将负责解锁关键部分。
离开临界区后,您应该调用 pthread_cleanup_pop(0) 将其删除。
IE
CRIITICAL_SECTION g_section;
void clean_crit_sec( void * )
{
LeaveCriticalSection( &g_section )
}
void *thrfunc( void * )
{
EnterCriticalSection( &g_section );
pthread_cleanup_push( clean_crit_sec, NULL );
// Do something that may be cancellable
LeaveCriticalSection( &g_section );
pthread_cleanup_pop( 0 );
}
这仍然会留下一个小的竞争条件,其中关键部分已被解锁,但如果线程在 Leave.. 和 cleanup_pop 之间取消,则仍可以执行清理处理程序。
您可以使用 1 调用 pthread_cleanup_pop ,这将执行您的清理代码,而不是自己解除临界区。IE
CRIITICAL_SECTION g_section;
void clean_crit_sec( void * )
{
LeaveCriticalSection( &g_section )
}
void *thrfunc( void * )
{
EnterCriticalSection( &g_section );
pthread_cleanup_push( clean_crit_sec, NULL );
// Do something that may be cancellable
pthread_cleanup_pop( 1 ); // this will pop the handler and execute it.
}