ios 如何使用 NSConditionLock?或 NSCondition
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6704072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I use NSConditionLock? Or NSCondition
提问by gurooj
I am try to make one function wait for another, and I would like to use NSCondionLock in order to accomplish this. I am not asking for help, but really hoping someone could show me a decent tutorial or example to explain NSConditionLock, or possibly suggest a better method.
我试图让一个函数等待另一个函数,我想使用 NSCondionLock 来完成这个。我不是在寻求帮助,而是真的希望有人可以向我展示一个体面的教程或示例来解释 NSConditionLock,或者可能提出更好的方法。
回答by DarkDust
EDIT:as @Bonshington commented, this answer refers to NSCondition(as opposed to NSConditionLock):
编辑:正如@Bonshington 所评论的,这个答案是指NSCondition(而不是NSConditionLock):
- (void) method1 {
[myCondition lock];
while (!someCheckIsTrue)
[myCondition wait];
// Do something.
[myCondition unlock];
}
- (void) method2 {
[myCondition lock];
// Do something.
someCheckIsTrue = YES;
[myCondition signal];
[myCondition unlock];
}
The someCheckIsTruecan be anything, it could be a simple BOOL variable or even something like [myArray count] == 0 && color == kColorRed, it doesn't matter. It only matters that in one method you check for a condition while you have the lockand in another method you make changes that can make the condition become true also while having the lock. The magic is the waitand signalpart: the waitactually unlocks the lock and reacquires it after some other thread called signal.
ThesomeCheckIsTrue可以是任何东西,它可以是一个简单的 BOOL 变量,甚至是类似的东西[myArray count] == 0 && color == kColorRed,都没有关系。重要的是,在一种方法中,您在拥有锁时检查条件,而在另一种方法中,您进行更改以使条件在拥有锁时也变为真。神奇之处在于waitandsignal部分:wait实际上解锁了锁并在其他线程调用之后重新获取它signal。
回答by vilanovi
For those that want a sample test class here I post what I did to play around and understand how NSCondition works.
对于那些想要一个示例测试类的人,我发布了我所做的尝试并了解 NSCondition 是如何工作的。
// --- MyTestClass.h File --- //
@interface MyTestClass
- (void)startTest;
@end
// --- MyTestClass.m File --- //
@implementation MyTestClass
{
NSCondition *_myCondition;
BOOL _someCheckIsTrue;
}
- (id)init
{
self = [super init];
if (self)
{
_someCheckIsTrue = NO;
_myCondition = [[NSCondition alloc] init];
}
return self;
}
#pragma mark Public Methods
- (void)startTest
{
[self performSelectorInBackground:@selector(_method1) withObject:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(5);
[self performSelectorInBackground:@selector(_method2) withObject:nil];
});
}
#pragma mark Private Methods
- (void)_method1
{
NSLog(@"STARTING METHOD 1");
NSLog(@"WILL LOCK METHOD 1");
[_myCondition lock];
NSLog(@"DID LOCK METHOD 1");
while (!_someCheckIsTrue)
{
NSLog(@"WILL WAIT METHOD 1");
[_myCondition wait];
NSLog(@"DID WAIT METHOD 1");
}
NSLog(@"WILL UNLOCK METHOD 1");
[_myCondition unlock];
NSLog(@"DID UNLOCK METHOD 1");
NSLog(@"ENDING METHOD 1");
}
- (void)_method2
{
NSLog(@"STARTING METHOD 2");
NSLog(@"WILL LOCK METHOD 2");
[_myCondition lock];
NSLog(@"DID LOCK METHOD 2");
_someCheckIsTrue = YES;
NSLog(@"WILL SIGNAL METHOD 2");
[_myCondition signal];
NSLog(@"DID SIGNAL METHOD 2");
NSLog(@"WILL UNLOCK METHOD 2");
[_myCondition unlock];
NSLog(@"DID UNLOCK METHOD 2");
}
@end
// --- Output --- //
/*
2012-11-14 11:01:21.416 MyApp[8375:3907] STARTING METHOD 1
2012-11-14 11:01:21.418 MyApp[8375:3907] WILL LOCK METHOD 1
2012-11-14 11:01:21.419 MyApp[8375:3907] DID LOCK METHOD 1
2012-11-14 11:01:21.421 MyApp[8375:3907] WILL WAIT METHOD 1
2012-11-14 11:01:26.418 MyApp[8375:4807] STARTING METHOD 2
2012-11-14 11:01:26.419 MyApp[8375:4807] WILL LOCK METHOD 2
2012-11-14 11:01:26.419 MyApp[8375:4807] DID LOCK METHOD 2
2012-11-14 11:01:26.420 MyApp[8375:4807] WILL SIGNAL METHOD 2
2012-11-14 11:01:26.420 MyApp[8375:4807] DID SIGNAL METHOD 2
2012-11-14 11:01:26.421 MyApp[8375:4807] WILL UNLOCK METHOD 2
2012-11-14 11:01:26.421 MyApp[8375:3907] DID WAIT METHOD 1
2012-11-14 11:01:26.421 MyApp[8375:4807] DID UNLOCK METHOD 2
2012-11-14 11:01:26.422 MyApp[8375:3907] WILL UNLOCK METHOD 1
2012-11-14 11:01:26.423 MyApp[8375:3907] DID UNLOCK METHOD 1
2012-11-14 11:01:26.423 MyApp[8375:3907] ENDING METHOD 1
*/
回答by GRiMe2D
NSConditionLockexample program.
NSConditionLock示例程序。
#import <Foundation/Foundation.h>
#define IDLE 0
#define START 1
#define TASK_1_FINISHED 2
#define TASK_2_FINISHED 3
#define CLEANUP_FINISHED 4
#define SHARED_DATA_LENGTH 1024 * 1024 * 1024
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSConditionLock *lock = [[NSConditionLock alloc] initWithCondition:IDLE];
char *shared_data = calloc(SHARED_DATA_LENGTH, sizeof(char));
[NSThread detachNewThreadWithBlock:^{
[lock lockWhenCondition:START];
NSLog(@"[Thread-1]: Task 1 started...");
for (size_t i = 0; i < SHARED_DATA_LENGTH; i++) {
shared_data[i] = 0x00;
}
[lock unlockWithCondition:TASK_1_FINISHED];
}];
[NSThread detachNewThreadWithBlock:^{
[lock lockWhenCondition:TASK_1_FINISHED];
NSLog(@"[Thread-2]: Task 2 started...");
for (size_t i = 0; i < SHARED_DATA_LENGTH; i++) {
char c = shared_data[i];
shared_data[i] = ~c;
}
[lock unlockWithCondition:TASK_2_FINISHED];
}];
[NSThread detachNewThreadWithBlock:^{
[lock lockWhenCondition:TASK_2_FINISHED];
NSLog(@"[Thread-3]: Cleaning up...");
free(shared_data);
[lock unlockWithCondition:CLEANUP_FINISHED];
}];
NSLog(@"[Thread-main]: Threads set up. Waiting for 2 task to finish");
[lock unlockWithCondition:START];
[lock lockWhenCondition:CLEANUP_FINISHED];
NSLog(@"[Thread-main]: Completed");
}
return 0;
}
回答by Ivan Smetanin
Swift 5version of @vilanovi answer from Playground:
来自 Playground 的 @vilanovi Swift 5版本的回答:
let myCondition = NSCondition()
var someCheckIsTrue = false
func method1() {
print("STARTING METHOD 1")
print("WILL LOCK METHOD 1")
myCondition.lock()
print("DID LOCK METHOD 1")
while (!someCheckIsTrue) {
print("WILL WAIT METHOD 1")
myCondition.wait()
print("DID WAIT METHOD 1")
}
print("WILL UNLOCK METHOD 1")
myCondition.unlock()
print("DID UNLOCK METHOD 1")
print("ENDING METHOD 1")
}
func method2() {
print("STARTING METHOD 2")
print("WILL LOCK METHOD 2")
myCondition.lock()
print("DID LOCK METHOD 2")
someCheckIsTrue = true
print("WILL SIGNAL METHOD 2")
myCondition.signal()
print("DID SIGNAL METHOD 2")
print("WILL UNLOCK METHOD 2")
myCondition.unlock()
print("DID UNLOCK METHOD 2")
print("ENDING METHOD 2")
}
DispatchQueue.global().async {
method1()
}
DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + 0.5) {
method2()
}

