大型中央调度块是否安全?

时间:2014-08-06 21:43:09

标签: c++ ios objective-c multithreading grand-central-dispatch

我有一个名为TestView的类,其中包含一个名为' loader'的实例变量。类型装载机。我在TestView上创建了一个方法来实例化加载器;然后在2秒后开始加载。

该方法如下所示:

-(void) createLoaderAndStartLoadingTwoSecondsLater{
    loader =  Loader();
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        printf("DISPATCHING AFTER %i seconds", i);
        loader->load(*urlRequest);
    });
}

在其他地方,有一种dealloc方法:

-(void) dealloc
{
    delete loader; 
}

在2秒计时器结束之前,可以调用dealloc。在这种情况下,如果dispatch_after块从未执行过,我希望它。

编辑: 我想这样做:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        printf("DISPATCHING AFTER %i seconds", i);
        if ( !hasBeenDeleted( loader ) ){
             loader->load(*urlRequest);
        }
    });

但我担心两件事:

  • 我不知道如何实现已被删除的功能
  • 我担心hasBeenDeleted将返回false,然后加载器将在另一个线程上被删除。

所以我真的很想这样做:

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        printf("DISPATCHING AFTER %i seconds", i);
        lockTheOtherThreads();
        if ( !hasBeenDeleted( loader ) ){
             loader->load(*urlRequest);
        }
        unlockTheOtherThreads();
    });

但我也不知道如何实现lockTheOtherThreads()

2 个答案:

答案 0 :(得分:3)

假设你有这个

@implementation MyClass {
    Loader *loader;
} 

-(void)createLoaderAndStartLoadingTwoSecondsLater{
    loader = new Loader();
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        printf("DISPATCHING AFTER %i seconds", i);
        loader->load(*urlRequest);
        //self->loader->load(*self->urlRequest);
    });
}

您创建的调度块将保留对self的强引用,这意味着在执行该块之前不会调用dealloc

同时使用unique_ptr,因此您无需致电删除。如果多个线程可以访问加载程序,则shared_ptratomic_load

@implementation MyClass {
    std::unique_ptr<Loader> loader;
} 

-(void)createLoaderAndStartLoadingTwoSecondsLater{
    loader.reset(new Loader()); // will delete previous loader if it exist
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        printf("DISPATCHING AFTER %i seconds", i);
        loader->load(*urlRequest);
    });
}

// you don't need dealloc anymore

更新

您可以捕获块中self的弱引用,以避免延长self的生命周期

-(void)createLoaderAndStartLoadingTwoSecondsLater{
    loader.reset(new Loader()); // will delete previous loader if it exist
    __weak typeof(self) weakSelf = self; // a weak reference to self
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        typeof(weakSelf) strongSelf = weakSelf;
        printf("DISPATCHING AFTER %i seconds", i);
        if (strongSelf) { // if still alive
            strongSelf->loader->load(*urlRequest);
        } // else it is deallocated
    });
}

答案 1 :(得分:0)

目前还不清楚你究竟想做什么。而且事情并非只是线程安全的,你需要说出你想做的事情。

调用dealloc后,当dealloc返回时,相关对象将消失。如果其他人试图保留它并不重要。似乎你在混淆Objective-C和C ++。在C ++中调用delete时,对象消失了。

我建议你阅读Objective-C中的弱指针并远离C ++。