【发布时间】:2013-03-18 01:30:51
【问题描述】:
我一直对如何编写以下代码来进行单元测试很感兴趣:
是否可以使用检查特定线程是否被阻塞的方法来扩展 NSThread?
现在我正在使用 NSCondition:Xcode 向我显示了由 -wait 调用以阻塞线程的链:
[NSCondition wait]
pthread_cond_wait$UNIX2003
_pthread_cond_wait
__psynch_cvwait
除了检查 NSCondition 完成的锁之外,如果可能的话,我非常感谢方法也适用于任何其他阻塞功能(调度信号量、条件锁、休眠线程等)——我不知道 Objective -C 内部,如果它们可以被一种方法捕获或者每个都需要自己的方法。
这是我想要实现的一个简单示例。这个神秘的方法叫做isBlocked。
// Some test case
// ...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
});
while(1) {
NSLog(@"Thread is blocked: %d", thread.isBlocked);
}
注意:我不擅长 C 和所有这些低级 POSIX 的东西,所以,请详细一点。
注意 2: 我也对适用于调度队列的解决方案感兴趣:如果有人可以告诉我如何测试 someQueue() 被 -[NSCondition wait] 阻塞的事实(而不是它将被阻止的事实(在运行 -[条件等待] 并设置块之前 fx 破解一些代码),但 线程/队列 被阻止的事实),我会接受这个作为一个答案,就像我使用 -[NSThread isBlocked] 方法一样。
注 3: 怀疑像“不可能”这样的坏消息,我声称任何关于捕捉 -[condition wait] 已运行并且线程被设置为阻塞的事实的想法(见注2) 表示赞赏,也可以作为答案接受!
UPDATE 1 致 Richard J. Ross III 的精彩回答。不幸的是,他的回答在我原来的例子中不起作用,这个版本更接近我的真实工作(尽管它与我最初提供的例子没有太大区别——很抱歉我没有将它包含在第一版问题):
// Example
// Here I've bootstrapped Richard's isLocking categories for both NSThread and NSCondition
// ...
// somewhere in SenTesting test case...
__block NSThread *thread;
NSCondition *condition = [NSCondition alloc] init];
__block BOOL wePassedBlocking = NO;
dispatch_async(someQueue(), ^{
thread = NSThread.currentThread;
[condition lock];
[condition wait];
[condition unlock];
wePassedBlocking = YES; // (*) This line is occasionally never reached!
});
while(!thread.isWaitingOnCondition); // I want this loop to exit after the condition really locks someQueue() and _thread_ __.
// sleep(1);
[condition lock];
[condition broadcast]; // BUT SOMETIMES this line is called before -[condition wait] is called inside someQueue() so the entire test case becomes blocked!
[condition unlock];
while(!wePassedBlocking); // (*) And so this loop occasionally never ends!
如果我取消注释 sleep(1) 测试开始工作非常稳定,没有任何偶然的锁定!
这导致我们遇到问题,Richard 的类别确实在实际阻塞完成前一行设置了状态,这意味着有时测试用例的主线程会捕获这个新状态在我们真正阻止 someQueue/thread 之前,因为 Richard 的代码不包含任何同步机制:@synchronized、NSLock 或类似的东西!我希望我能清楚地解释这个棘手的案例。对于任何对我在这里发布的内容有疑问的人,我想说我也一直在尝试多个队列甚至更复杂的案例,如果需要,我准备提供更多示例。理查德,再次感谢您的努力,如果您理解我的这些观点,让我们一起思考更多!
更新 2
我看到了死胡同:显然,要真正设置 waitingOnCondition 的状态,我们需要将此状态的更改包装在一些同步闭包中,但问题是关闭一个,解锁同步锁,应该在-[条件等待]之后调用,但是不能,因为线程已经被阻塞了。再次,我希望我描述得很清楚。
【问题讨论】:
-
线程未“锁定”。一个线程可以持有一个锁,或者可能等待一个锁,不过——你的意思是其中之一吗?
-
对不起,如果我没有使用正确的术语。但我确信我的例子确实描述了我想要的,不是吗? -[condition wait] “停止”线程,直到从其他线程调用 -[condition signal] 的那一刻 - 我想了解条件设置为等待并且线程已停止滚动的事实.
-
@Stanislaw 只需在 NSThread 上写一个类别来处理它。
-
@CodaFi,这就是我在这里要问的问题;)我不知道该怎么做。
-
我敢说,大多数经验丰富的多线程熟悉的开发人员不会使用,也不需要
isBlocked之类的东西。它最终可能最终会背叛你。
标签: objective-c locking pthreads