C 等待条件变量时,取消点清理需要解锁互斥锁吗?

C 等待条件变量时,取消点清理需要解锁互斥锁吗?,c,pthreads,locking,condition-variable,code-cleanup,C,Pthreads,Locking,Condition Variable,Code Cleanup,在pthread库中有取消点的概念。pthread取消点可以中止可能阻塞执行更长时间(或等待某些resources…)的大多数系统函数 假设有一些数据受条件变量保护,该变量在线程中执行,如下面的伪代码所示。此线程有一个设置清理过程,在向该线程发出取消请求时调用该过程 THREAD_CLEANUP_PROC { UNLOCK(mutex) // Is this unlock required? } THREAD_PROC { SET THREAD_CLEANUP = THREAD

在pthread库中有取消点的概念。pthread取消点可以中止可能阻塞执行更长时间(或等待某些resources…)的大多数系统函数

假设有一些数据受条件变量保护,该变量在线程中执行,如下面的伪代码所示。此线程有一个设置清理过程,在向该线程发出取消请求时调用该过程

THREAD_CLEANUP_PROC {
    UNLOCK(mutex) // Is this unlock required?
}

THREAD_PROC {
    SET THREAD_CLEANUP = THREAD_CLEANUP_PROC
    LOOP {
        LOCK(mutex)
        WHILE (condition == false) {
            condition.WAIT(mutex) // wait interrupted, cancel point is called
        }
        // ... we have the lock
        UNLOCK(mutex)
        condition.NOTIFY_ALL()

        read(descriptor); // wait for some data on a file descriptor while lock is not acquired
    }
}
如果有人在等待条件变量时取消线程(pthread_cancel()),那么关于
pthread_cond_wait
的文档会说,线程在获取锁时会被解除阻止,并在线程结束之前开始执行清理处理程序


清理处理程序现在负责解锁该锁(互斥锁),这是真的吗?如果有另一种阻塞方法,如
read
,在等待数据时阻塞,但不获取锁,会怎么样?在这种情况下,
read
也会被取消阻止,并且像以前一样调用清理处理程序。只有这一次清理处理程序才不会解锁互斥锁。我说得对吗。如果是,处理这种情况的最佳方法是什么?有没有应该遵循的共同概念?

线程取消很混乱。一般来说,你不应该这样做

在pthread库中有取消点的概念

pthread取消点可以中止可能阻塞执行更长时间(或等待某些resources…)的大多数系统函数

不完全是。您描述的许多功能都是取消点。具有“延迟”取消类型的线程在调用作为取消点的函数时将中止,前提是该函数当前可取消并且有一个挂起的取消请求。这并不意味着这样的函数可以被线程取消中断。具有“异步”取消的线程可以在任何时候或多或少地取消,包括在阻塞长时间运行的任务时,但在这种情况下取消点是不相关的

如果有人在等待条件变量时取消线程(pthread_cancel()),那么关于
pthread_cond_wait
的文档会说,线程在获取锁时会被解除阻止,并在线程结束之前开始执行清理处理程序

是,前提是线程具有“延迟”取消类型

清理处理程序现在负责解锁该锁(互斥锁),这是真的吗

对。在这种情况下,线程在开始其取消过程时保持互斥锁锁定。如果它在终止前没有解锁互斥锁,那么至少你会遇到一个大麻烦。某些类型的互斥体(由pthreads支持)可能提供了一种从这种情况中恢复的方法,但最好避免这种情况

如果有另一种阻塞方法,比如read,在等待数据时阻塞,但不获取锁,会怎么样?在这种情况下,读取也会被取消阻止,清理处理程序会像以前一样被调用。只有这一次清理处理程序才不会解锁互斥锁。我说得对吗

同样,有各种类型的互斥体,情况可能会因您使用的不同而有所不同,但到目前为止,最好的选择是小心避免任何线程试图解锁未锁定的互斥体

如果是,处理这种情况的最佳方法是什么

处理这种情况的最好办法是首先避免它。不要使用线程取消,特别是对于容易发生此类问题的线程,这些问题实际上很常见


相反,请仔细编写多线程程序,以便为自己提供及时关闭线程或整个程序的替代方法。有一大堆这样的技术,我无法在一个SO的答案中合理地总结。

线程取消很麻烦。一般来说,你不应该这样做

在pthread库中有取消点的概念

pthread取消点可以中止可能阻塞执行更长时间(或等待某些resources…)的大多数系统函数

不完全是。您描述的许多功能都是取消点。具有“延迟”取消类型的线程在调用作为取消点的函数时将中止,前提是该函数当前可取消并且有一个挂起的取消请求。这并不意味着这样的函数可以被线程取消中断。具有“异步”取消的线程可以在任何时候或多或少地取消,包括在阻塞长时间运行的任务时,但在这种情况下取消点是不相关的

如果有人在等待条件变量时取消线程(pthread_cancel()),那么关于
pthread_cond_wait
的文档会说,线程在获取锁时会被解除阻止,并在线程结束之前开始执行清理处理程序

是,前提是线程具有“延迟”取消类型

清理处理程序现在负责解锁该锁(互斥锁),这是真的吗

对。在这种情况下,线程在开始其取消过程时保持互斥锁锁定。如果它在终止前没有解锁互斥锁,那么至少你会遇到一个大麻烦。某些类型的互斥体(由pthreads支持)可能提供了一种从这种情况中恢复的方法,但最好避免这种情况

如果有另一种阻塞方法,比如read,在等待数据时阻塞,但不获取锁,会怎么样?在这种情况下,读取也会被取消阻止,清理处理程序会像以前一样被调用。只有这一次清理处理程序才不会解锁互斥锁。我说得对吗

<
THREAD_CLEANUP_PROC {
    UNLOCK(mutex) // Is this unlock required? YES
}

THREAD_PROC {
    LOOP {
        LOCK(mutex)
        SET THREAD_CLEANUP_PUSH = THREAD_CLEANUP_PROC // After adquire the lock
        WHILE (condition == false) {
            condition.WAIT(mutex) // wait interrupted, cancel point is called
        }
        // ... we have the lock
        THEAD_CLEANUP_POP(1) // This unlock the mutex and remove the cleanup
        // UNLOCK(mutex)
        condition.NOTIFY_ALL()

        read(descriptor); // wait for some data on a file descriptor while lock is not acquired
    }
}