C++ 大中央调度模块是线程安全的吗?

C++ 大中央调度模块是线程安全的吗?,c++,ios,objective-c,multithreading,grand-central-dispatch,C++,Ios,Objective C,Multithreading,Grand Central Dispatch,我有一个名为TestView的类,它有一个名为loader的实例变量,类型为loader。我在TestView上创建了一个方法来实例化加载程序;然后在2秒钟后开始加载 该方法如下所示: -(void) createLoaderAndStartLoadingTwoSecondsLater{ loader = Loader(); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_g

我有一个名为TestView的类,它有一个名为loader的实例变量,类型为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; 
}
dealloc有可能在2秒计时器过去之前被调用。在这种情况下,我希望它如果调度_后块从未执行

编辑: 我想这样做:

  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);
        }
    });
  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();
    });
但我担心两件事:

  • 我不知道如何实现已删除的函数
  • 我担心hasbeendelete将返回false,然后加载程序将在另一个线程上被删除
所以我真的想这样做:

  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);
        }
    });
  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()

不清楚您实际上想做什么。事情不仅仅是“线程安全”,你需要说出你想做什么

调用dealloc后,当dealloc返回时,相关对象将消失。如果有人试图保留它,这并不重要。看起来你正在混合Objtovi-C和C++。当C++中删除时,对象已经消失。
<>我建议你读ObjuleC中的弱指针,远离C++。p> 不清楚你到底想做什么。事情不仅仅是“线程安全”,你需要说出你想做什么

调用dealloc后,当dealloc返回时,相关对象将消失。如果有人试图保留它,这并不重要。看起来你正在混合Objtovi-C和C++。当C++中删除时,对象已经消失。
<>我建议你读ObjuleC中的弱指针,远离C++。p> 不清楚你到底想做什么。事情不仅仅是“线程安全”,你需要说出你想做什么

调用dealloc后,当dealloc返回时,相关对象将消失。如果有人试图保留它,这并不重要。看起来你正在混合Objtovi-C和C++。当C++中删除时,对象已经消失。
<>我建议你读ObjuleC中的弱指针,远离C++。p> 不清楚你到底想做什么。事情不仅仅是“线程安全”,你需要说出你想做什么

调用dealloc后,当dealloc返回时,相关对象将消失。如果有人试图保留它,这并不重要。看起来你正在混合Objtovi-C和C++。当C++中删除时,对象已经消失。
<>我建议你读ObjuleC中的弱指针,远离C++。p> 假设你有这个

@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\u ptr
,这样就不需要调用delete。或者如果多个线程可以访问加载程序,则使用
原子加载
共享\u ptr

@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

假设你有这个

@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\u ptr
,这样就不需要调用delete。或者如果多个线程可以访问加载程序,则使用
原子加载
共享\u ptr

@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

假设你有这个

@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\u ptr
,这样就不需要调用delete。或者如果多个线程可以访问加载程序,则使用
原子加载
共享\u ptr

@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

假设你有这个

@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\u ptr
,这样就不需要调用delete。或者如果多个线程可以访问加载程序,则使用
原子加载
共享\u ptr

@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

你的最后一段很混乱。“保证执行而不切换线程”是什么意思?无论如何,这与我能想到的任何“线程安全”的定义都不相符。你会怎么检查空值?你认为这将如何让你“处理完毕”?谢谢。当我写它的时候,我没有意识到这是多么的不清楚。我编辑了这个问题,希望能把事情弄清楚。你不应该用一个已经被删除的测试来思考。相反,您应该通过维护强引用来确保它不会被删除。如果你想取消加载,你应该用另一种方式。例如,在已知运行循环(即主运行循环)上使用
NSTimer
,并使其无效以取消它。或者,类似地,使用
-performSelector:withObject:afterDelay:
,然后使用
+cancel先前的performrequestswithtarget:selector:object:
将其取消。在任何情况下,只要延迟的代码挂起,就应该保留加载程序。把它安排好,取消它就是释放它的原因。啊哈,谢谢。实际上,我只想取消异步调度。我不经常使用iOS,而且我忘记了存在
performSelector:withObject:afterDelay
cancelPreviousPerformRequestsWithTarget:selector:object
。这应该可以解决这个问题。你的最后一段很混乱。“保证执行而不切换线程”是什么意思?无论如何,这与我能想到的任何“线程安全”的定义都不相符。你会怎么检查空值?你认为这将如何让你“处理完毕”?谢谢。当我写它的时候,我没有意识到这是多么的不清楚。我编辑了这个问题,希望能把事情弄清楚。你不应该用错误的方式思考