首页 > 其他分享 >执行异步派发时, 需要拷贝块

执行异步派发时, 需要拷贝块

时间:2024-06-11 15:32:14浏览次数:19  
标签:异步 派发 dispatch queue value async 拷贝 block

dispatch_async 在执行异步派发时,需要拷贝 block。

Block 的行为

在 Objective-C 中,block 是带有自动变量(局部变量)和堆栈信息的代码段。当你声明一个 block,它默认存储在栈上。这意味着,当函数返回时,block 可能不再有效。为了确保 block 在需要时仍然有效,block 通常会被拷贝到堆上。

dispatch_async 的行为

当你使用 dispatch_async 将一个 block 任务派发到一个队列时,需要确保这个 block 在队列执行时仍然有效。为了做到这一点,dispatch_async 会拷贝这个 block,并将拷贝后的 block 提交到目标队列。

代码分析

来看一个简单的代码示例:

dispatch_queue_t queue = dispatch_queue_create("com.example.queue", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue, ^{
    NSLog(@"Hello from block");
});

在这段代码中,dispatch_async 做了以下工作:

  1. Block 的创建

    • ^{ NSLog(@"Hello from block"); } 是一个 block,默认在栈上。
  2. Block 的拷贝

    • dispatch_async 被调用时,它会拷贝这个 block 到堆上,以确保 block 在异步执行时依然有效。
  3. Block 的提交

    • 拷贝后的 block 被提交到 queue 队列。
  4. Block 的执行

    • 队列异步执行这个 block。

为什么需要拷贝

考虑以下示例:

void myFunction() {
    int value = 10;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Value: %d", value);
    });
    // myFunction 返回后,value 变量会被销毁
}

myFunction 中,value 是一个局部变量,存储在栈上。如果 block 没有被拷贝到堆上,myFunction 返回后,value 变量可能已经被销毁,而 block 中引用的 value 变得无效。

通过将 block 拷贝到堆上,block 会持有 value 的拷贝,确保 dispatch_async 中的 block 可以安全地使用 value,即使 myFunction 已经返回。

概述

  • 拷贝行为: dispatch_async 会拷贝 block,以确保 block 在异步执行时有效。
  • 安全性: 这样做是为了确保 block 中引用的变量在函数返回后依然有效,防止引用无效的局部变量。

这个行为是 GCD (Grand Central Dispatch) 的设计之一,旨在确保异步任务的安全性和稳定性。

标签:异步,派发,dispatch,queue,value,async,拷贝,block
From: https://blog.csdn.net/qfeung/article/details/139599429

相关文章

  • 零拷贝
    普通流程网络IO读写流程应用进程的每一次写操作,都会把数据写到用户空间的缓冲区中,再由CPU将数据拷贝到系统内核的缓冲区中,之后再由DMA将这份数据拷贝到网卡中,最后由网卡发送出去。这里我们可以看到,一次写操作数据要拷贝两次才能通过网卡发送出去,而用户进程的读操作则是将整个......
  • (6)同步复位异步释放电路
    一、复位电路时序电路为双稳态电路,因此必须要有复位信号,而组合电路没有存储功能,因此不需要复位信号电路中的复位有两种形式:1.同步复位敏感列表中只有时钟信号没有复位信号2.异步复位敏感列表中不仅有时钟而且有复位信号为避免在释放......
  • Python中的浅拷贝与深拷贝
    Python中值的拷贝可分为直接赋值,浅拷贝与深拷贝直接赋值:即为对象的引用,赋值前后的对象均指向同一对象浅拷贝:拷贝父对象,拷贝前与拷贝后的对象均为独立的对象,但是他们的子对象都仍然指向同一对象深拷贝:完全拷贝父对象及子对象,拷贝前与拷贝后的对象均独立存在演示代码如下import......
  • 论述MySQL的同异步复制
    MySQL的复制功能是数据库系统中一个重要的特性,它可以实现数据的冗余备份和分布式读写,提高系统的可靠性和性能。MySQL的复制主要分为异步复制、半同步复制和同步复制,这三种复制方式在机制和使用场景上有显著的不同。异步复制特点主从模式:在异步复制中,主库(Master)将数据的变更......
  • 2024-06-05 拷贝、函数、装饰器、迭代生成器
    一、浅拷贝lists=[1,2,[6]]内存空间不同,浅拷贝内容不变 new_lists=copy(lists)lists.append(7)print(lists,new_lists)//[1,2,[6],7][1,2,[6]]改变列表中内容,内存空间相同,数值改变new_lists=copy(lists)lists[-1].append(7)print(lists,new_lists)//[......
  • 按键中断驱动程序-异步通知
    在前面的休眠-唤醒、POLL机制中,都是通过休眠等待某一个事件的发生,而程序一旦陷入休眠,就没法再执行其它任务,相当于整个程序卡死了。在很多的场景中,如果发生了某一个事件我们就去处理它,没有发生事件那就可以做其它的事情。这种正常执行程序,当中断发生时才去执行的方式就叫做异步通知......
  • C++Primer Plus 第12章 类和动态内存分配 12.10编程练习第2题new,delete的指向深度拷
    系列文章目录提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加例如:本章练习第2题涉及标准函数及关键词toupper,tolower(),strcpy_s(),strcat_s(),strcmp,strlen(),new[],delete[].实现如下效果输出应与下面相似:Pleaseenteryourname:FrettaFarboMynameis......
  • 搭建RocketMQ主从异步集群
    搭建RocketMQ主从异步集群1、RocketMQ集群模式  为了追求更好的性能,RocketMQ的最佳实践方式都是在集群模式下完成的。RocketMQ官方提供了三种集群搭建方式:2主2从异步通信方式:使用异步方式进行主从之间的数据复制。吞吐量大,但可能会丢消息。使用conf/2m-2s-async文件夹......
  • 文件IO——用read与write实现图片拷贝
    1#include<stdio.h>2#include<sys/types.h>3#include<sys/stat.h>4#include<fcntl.h>5#include<unistd.h>6#include<string.h>7intmain(intargc,constchar*argv[])8{910intpath=......
  • C++Primer Plus 第12章 类和动态内存分配 12.10编程练习第1题new,delete的指向深度拷
    C++PrimerPlus第12章类和动态内存分配12.10编程练习第1题`提示:练习一定要动手操作涉及标准函数及关键词1,new[],delete[],strlen(),strcpy_s(),cout,endl,explicit例如:1,对于下面的类的声明:`提示:设计数组和字符串的new,delete文章目录C++PrimerPlus第12章类......