【问题标题】:Unlocking a thread using NSCondition (Objective-C)使用 NSCondition 解锁线程(Objective-C)
【发布时间】:2015-07-07 23:09:12
【问题描述】:

我正在使用 Objective-C 并尝试使用需要相互通信的线程。

代码如下:

-(id) init
{
    self = [super init];
    if (self) {
        _event = [[MyTestClass alloc]init]; //MyTestClass has a property of type NSCondition
    }
    return self;
}


-(void) func1
{
NSLog(@"The Function 1 is being called");
NSLog(@"Locking The First function");
[self.event.myCondition lock];
[self.event.myCondition wait];
NSLog(@"Resuming Function 1");
    NSLog(@"This is a test 1 ");
    NSLog(@"This is a test 2");
    NSLog(@"Terminating func 1");
}
-(void) func2
{
    NSLog(@"2");
    NSLog(@"Hey Hey Hey How are you 0 ");
    NSLog(@"Hey Hey Hey How are you 1 ");
    NSLog(@"Hey Hey Hey How are you 2");
    NSLog(@"Signaling function 1");
    [self.event.myCondition signal];
    NSLog(@"Hey Hey Hey How are you 3");
    NSLog(@"Terminating func 2");
}

我在两个单独的线程上运行 func1 和 func2,如下所示

- (void)viewDidLoad {
    [super viewDidLoad];
    SuperTestClass * n = [[SuperTestClass alloc]init];
    // Do any additional setup after loading the view, typically from a nib.
    MyTestClass * m = [[MyTestClass alloc]init];
    dispatch_queue_t newQueue =     dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
    dispatch_group_t newGroup = dispatch_group_create();
    dispatch_group_async(newGroup, newQueue, ^{
        [n func1];
    });
    dispatch_group_async(newGroup, newQueue, ^{
        [n func2];
    });
    dispatch_group_wait(newGroup, DISPATCH_TIME_FOREVER);
    NSLog(@"All process have terminated");
}

运行此代码时出现以下错误

2015-07-07 19:05:54.528 signalingInObjectiveC[31617:319892] 2
2015-07-07 19:05:54.528 signalingInObjectiveC[31617:319894] The Function 1 is being called
2015-07-07 19:05:54.529 signalingInObjectiveC[31617:319892] Hey Hey Hey How are you 0 
2015-07-07 19:05:54.529 signalingInObjectiveC[31617:319894] Locking The First function
2015-07-07 19:05:54.529 signalingInObjectiveC[31617:319892] Hey Hey Hey How are you 1 
2015-07-07 19:05:54.529 signalingInObjectiveC[31617:319892] Hey Hey Hey How are you 2 
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319892] Signaling function 1
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319892] Hey Hey Hey How are you 3 
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319894] Resuming Function 1
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319892] Terminating func 2
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319894] This is a test 1
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319894] This is a test 2
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319894] Terminating func 1
2015-07-07 19:05:54.530 signalingInObjectiveC[31617:319870] All process have terminated
2015-07-07 19:05:54.535 signalingInObjectiveC[31617:319870] *** -[NSCondition dealloc]: condition (<NSCondition: 0x7fa2aa517180> '(null)') deallocated while still in use
2015-07-07 19:05:54.535 signalingInObjectiveC[31617:319870] *** Break on _NSLockError() to debug.

我想知道我的解锁方式出了什么问题。

【问题讨论】:

    标签: objective-c iphone multithreading thread-safety nscondition


    【解决方案1】:

    您在滥用 NSCondition 类。检查apple doc。 本质上,POSIX 条件与保护条件测试的共享数据的互斥锁一起使用。你应该有类似的东西(其中 P 是共享状态的布尔谓词)

    线程#1:

    [cond lock];
    while (!P(state)) {
       [cond wait];
    }
    // invariant: if you get here, P(state) is true
    ... Use the state... // it is protected by the lock
    [cond unlock];
    

    线程#2:

    [cond lock];
    ... change the state ... // this potentially changes the value of P
    [cond signal];  // or [cond broadcast]
    [cond unlock];
    

    线程 #2 修改共享状态(例如,在共享 buf 中存入一条消息)并通知线程 #1。在线程#2 放弃锁之前,线程#1 无法唤醒。请注意线程 #1 中的调用 [cond wait] 如何以原子方式解锁互斥锁并进入睡眠状态。循环是必要的,原因有两个:

    1. 您可能会获得虚假唤醒(无缘无故,因此无法保证 P(state) 为真。
    2. 您可以让多个线程执行线程#1 所描述的操作。如果线程#2 只存放一条数据,那么只有一个执行消费的线程实际上可以获取一个数据项,并且“消费它”将使 P(state) 无效,因此其他线程将立即重新进入睡眠状态。

    归根结底,您的代码不正确,因为您未能解锁条件并在锁定时将其销毁。您没有遵循使用 POSIX 条件的编码模式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-07
      • 2010-11-15
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多