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 someCheckIsTrue
can 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 wait
and signal
part: the wait
actually unlocks the lock and reacquires it after some other thread called signal
.
ThesomeCheckIsTrue
可以是任何东西,它可以是一个简单的 BOOL 变量,甚至是类似的东西[myArray count] == 0 && color == kColorRed
,都没有关系。重要的是,在一种方法中,您在拥有锁时检查条件,而在另一种方法中,您进行更改以使条件在拥有锁时也变为真。神奇之处在于wait
andsignal
部分: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
NSConditionLock
example 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()
}