gpt4 book ai didi

浅析iOS应用开发中线程间的通信与线程安全问题

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 25 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章浅析iOS应用开发中线程间的通信与线程安全问题由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

线程间的通信   简单说明 线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信   线程间通信的体现 1个线程传递数据给另1个线程 在1个线程中执行完特定任务后,转到另1个线程继续执行任务   线程间通信常用方法 。

复制代码 代码如下:

- (void)performselectoronmainthread:(sel)aselector withobject:(id)arg waituntildone:(bool)wait;
- (void)performselector:(sel)aselector onthread:(nsthread *)thr withobject:(id)arg waituntildone:(bool)wait;

线程间通信示例 – 图片下载 。

  。

浅析iOS应用开发中线程间的通信与线程安全问题

  。

复制代码 代码如下:

// //  yyviewcontroller.m //  06-nsthread04-线程间通信 // //  created by apple on 14-6-23. //  copyright (c) 2014年 itcase. all rights reserved. // 。

  。

#import "yyviewcontroller.h" @interface yyviewcontroller () @property (weak, nonatomic) iboutlet uiimageview *iconview; @end 。

  。

复制代码 代码如下:

@implementation yyviewcontroller 。

  。

- (void)viewdidload {     [super viewdidload]; } 。

-(void)touchesbegan:(nsset *)touches withevent:(uievent *)event { 。

// 在子线程中调用download方法下载图片     [self performselectorinbackground:@selector(download) withobject:nil]; } 。

  。

-(void)download {     //1.根据url下载图片     //从网络中下载图片     nsurl *urlstr=[nsurl urlwithstring:@"fdsf"],

    //把图片转换为二进制的数据     nsdata *data=[nsdata datawithcontentsofurl:urlstr];//这一行操作会比较耗时 。

    //把数据转换成图片     uiimage *image=[uiimage imagewithdata:data];       //2.回到主线程中设置图片     [self performselectoronmainthread:@selector(settingimage:) withobject:image waituntildone:no]; } 。

  。

//设置显示图片 -(void)settingimage:(uiimage *)image {     self.iconview.image=image; } 。

@end 。

代码2:

复制代码 代码如下:

// //  yyviewcontroller.m //  06-nsthread04-线程间通信 // //  created by apple on 14-6-23. //  copyright (c) 2014年 itcase. all rights reserved. // 。

  。

#import "yyviewcontroller.h" #import <nsdata.h> 。

@interface yyviewcontroller () @property (weak, nonatomic) iboutlet uiimageview *iconview; @end 。

  。

复制代码 代码如下:

@implementation yyviewcontroller 。

  。

- (void)viewdidload {     [super viewdidload]; } 。

  -(void)touchesbegan:(nsset *)touches withevent:(uievent *)event { // 在子线程中调用download方法下载图片 。

    [self performselectorinbackground:@selector(download) withobject:nil]; } 。

  -(void)download { 。

    //1.根据url下载图片     //从网络中下载图片     nsurl *urlstr=[nsurl urlwithstring:@"fdsf"],

    //把图片转换为二进制的数据     nsdata *data=[nsdata datawithcontentsofurl:urlstr];//这一行操作会比较耗时 。

    //把数据转换成图片     uiimage *image=[uiimage imagewithdata:data],

    //2.回到主线程中设置图片     //第一种方式 //    [self performselectoronmainthread:@selector(settingimage:) withobject:image waituntildone:no],

    //第二种方式     //    [self.imageview performselector:@selector(setimage:) onthread:[nsthread mainthread] withobject:image waituntildone:no],

    //第三种方式    [self.iconview performselectoronmainthread:@selector(setimage:) withobject:image waituntildone:no]; } 。

//设置显示图片 //-(void)settingimage:(uiimage *)image //{ //    self.iconview.image=image; //} 。

@end 。

  。

线程安全   1、多线程的安全隐患 资源共享 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源 比如多个线程访问同一个对象、同一个变量、同一个文件 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题 示例一:

浅析iOS应用开发中线程间的通信与线程安全问题

示例二:

浅析iOS应用开发中线程间的通信与线程安全问题

问题代码:

复制代码 代码如下:

// //  yyviewcontroller.m //  05-线程安全 // //  created by apple on 14-6-23. //  copyright (c) 2014年 itcase. all rights reserved. // 。

  。

#import "yyviewcontroller.h" 。

@interface yyviewcontroller () //剩余票数 。

@property(nonatomic,assign) int leftticketscount; @property(nonatomic,strong)nsthread *thread1; @property(nonatomic,strong)nsthread *thread2; @property(nonatomic,strong)nsthread *thread3,

@end 。

  。

复制代码 代码如下:

@implementation yyviewcontroller 。

  。

- (void)viewdidload {     [super viewdidload],

    //默认有20张票 。

    self.leftticketscount=10,

    //开启多个线程,模拟售票员售票 。

    self.thread1=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil],

    self.thread1.name=@"售票员a",

    self.thread2=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil],

    self.thread2.name=@"售票员b",

    self.thread3=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil];     self.thread3.name=@"售票员c"; } 。

  -(void)selltickets {     while (1) {         //1.先检查票数         int count=self.leftticketscount;         if (count>0) {             //暂停一段时间             [nsthread sleepfortimeinterval:0.002],

            //2.票数-1            self.leftticketscount= count-1;               //获取当前线程             nsthread *current=[nsthread currentthread];             nslog(@"%@--卖了一张票,还剩余%d张票",current,self.leftticketscount);         }else         {             //退出线程             [nsthread exit];         }     } } 。

-(void)touchesbegan:(nsset *)touches withevent:(uievent *)event {     //开启线程 。

   [self.thread1 start];     [self.thread2 start];     [self.thread3 start],

} 。

@end 。

打印结果:

  。

浅析iOS应用开发中线程间的通信与线程安全问题

2、安全隐患分析 。

浅析iOS应用开发中线程间的通信与线程安全问题

浅析iOS应用开发中线程间的通信与线程安全问题

3、如何解决   互斥锁使用格式 @synchronized(锁对象) { // 需要锁定的代码  } 注意:锁定1份代码只用1把锁,用多把锁是无效的   代码示例:

复制代码 代码如下:

// //  yyviewcontroller.m //  05-线程安全 // //  created by apple on 14-6-23. //  copyright (c) 2014年 itcase. all rights reserved. // 。

  。

#import "yyviewcontroller.h" 。

@interface yyviewcontroller () 。

//剩余票数 @property(nonatomic,assign) int leftticketscount; @property(nonatomic,strong)nsthread *thread1; @property(nonatomic,strong)nsthread *thread2; @property(nonatomic,strong)nsthread *thread3; @end 。

@implementation yyviewcontroller 。

- (void)viewdidload {     [super viewdidload];     //默认有20张票     self.leftticketscount=10;     //开启多个线程,模拟售票员售票 。

    self.thread1=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil],

    self.thread1.name=@"售票员a",

    self.thread2=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil],

    self.thread2.name=@"售票员b",

    self.thread3=[[nsthread alloc]initwithtarget:self selector:@selector(selltickets) object:nil],

    self.thread3.name=@"售票员c"; } 。

-(void)selltickets {     while (1) {         @synchronized(self){//只能加一把锁         //1.先检查票数 。

        int count=self.leftticketscount;         if (count>0) {             //暂停一段时间             [nsthread sleepfortimeinterval:0.002];             //2.票数-1 。

           self.leftticketscount= count-1;             //获取当前线程             nsthread *current=[nsthread currentthread];             nslog(@"%@--卖了一张票,还剩余%d张票",current,self.leftticketscount),

        }else         {             //退出线程             [nsthread exit];         }         }     } } 。

-(void)touchesbegan:(nsset *)touches withevent:(uievent *)event { 。

    //开启线程    [self.thread1 start];     [self.thread2 start];     [self.thread3 start]; } 。

@end 。

执行效果图 。

  。

浅析iOS应用开发中线程间的通信与线程安全问题

互斥锁的优缺点 优点:能有效防止因多线程抢夺资源造成的数据安全问题 缺点:需要消耗大量的cpu资源   互斥锁的使用前提:多条线程抢夺同一块资源 相关专业术语:线程同步,多条线程按顺序地执行任务 互斥锁,就是使用了线程同步技术   四:原子和非原子属性   oc在定义属性时有nonatomic和atomic两种选择 atomic:原子属性,为setter方法加锁(默认就是atomic) nonatomic:非原子属性,不会为setter方法加锁   atomic加锁原理 。

复制代码 代码如下:

@property (assign, atomic) int age,

  。

- (void)setage:(int)age { 。

    @synchronized(self) {        _age = age;     } } 。

原子和非原子属性的选择 nonatomic和atomic对比 。

  。

  • atomic:线程安全,需要消耗大量的资源
  • nonatomic:非线程安全,适合内存小的移动设备 

ios开发的建议 。

  • 所有属性都声明为nonatomic
  • 尽量避免多线程抢夺同一块资源
  • 尽量将加锁、资源抢夺的业务逻辑交给服务器端处理,减小移动客户端的压力

最后此篇关于浅析iOS应用开发中线程间的通信与线程安全问题的文章就讲到这里了,如果你想了解更多关于浅析iOS应用开发中线程间的通信与线程安全问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com