美文网首页
多线程01 pthread NSThread 多线程的资源共享问

多线程01 pthread NSThread 多线程的资源共享问

作者: xwf_code | 来源:发表于2016-10-17 20:40 被阅读0次

凡是跟UI相关的都是在主线程执行的

UIKit类库的线程都是不安全的 所以我们需要在主线程上更新UI 因此主线程又叫UI线程

多线程的核心思想 : 就是把耗时操作放在后台执行,避免耗时操作卡死UI

currentThread : 查看当前线程

NSLog(@"%@",[NSThread currentThread]);

同步和异步

同步和异步是任务 / 代码 执行的两种方式

同步--->多个任务按顺序依次执行,就是同步执行

异步--->多个任务同时执行,就是异步执行

pthread

参数1 : 子线程的ID / 标识

在C语言中,一般带`_t` / `_ref`标识数据类型

参数2 : 子线程的属性,一般传NULL

NULL : 表示空地址,一般在C语言使用;

nil : 表示空对象,一般在OC使用;

其实,NULLh和nil本质上没有半点儿区别

参数3 : 子线程需要执行的函数

void *(*)(void *) : 表示指向函数的指针,即函数名;函数名就是表示函数地址;

数组地址就是数组名或者数组第0个角标元素的地址

void * 表示可以指向任何地址的指针,代表任意数据类型;类似于OC的id;

返回值    函数名    函数参数

void *    (*)    (void *)

参数4 : 传入到子线程需要执行的函数的参数

返回值 : int;在很多C语言框架中,并不是遵守非零既真;因为成功的结果只有一个,0是唯一的;失败的原因有很多;

线程调试 : 查看方法执行的线程是否是主线程或者子线程

{number = 1, name = main} : 表示主线程

{number = 3, name = (null)} : 只要number != 1 就表示子线程

提示 : 千万不要纠结number到底等于几,系统分配的

// 参数1

pthread_t ID;

// 创建了一个子线程,执行demo函数

int result = pthread_create(&ID, NULL, demo, NULL);

// 判断创建子线程是否成功

if (result == 0) {

NSLog(@"创建子线程成功");

} else {

NSLog(@"创建子线程失败");

}

子线程执行的函数

*/

void *demo(void *param)

{

NSString *str = (__bridge NSString *)(param);

// currentThread : 查看当前线程

NSLog(@"demo %@ - %@",[NSThread currentThread],str);

return NULL;

}

NSThread创建线程三种方式

[self performSelectorInBackground:@selector(demo:) withObject:@"perform"];

以上参数介绍:

1.NSObject分类方法创建子线程

2.不可以拿到线程对象

3.不需要手动启动线程

[NSThread detachNewThreadSelector:@selector(demo:) toTarget:self withObject:@"detach"];

以上参数介绍:

1.类方法创建子线程

2.不可以拿到线程对象

3.不需要手动启动线程

// 创建线程对象

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo:) object:@"alloc"];

// 启动线程

[thread start];

以上参数介绍:

1.构造方法创建子线程

2.可以拿到线程对象

3.需要手动启动线程

通知主线程刷新UI

// waitUntilDone : 是否等待updateUI执行完,再执行后面的代码,一般传入NO

[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:NO];

关于以上使用调用方法中-target和selector关系

@selector中需要传入一个方法

而target中需要传入对象告诉系统 这个方法是哪个对象的

线程的声明周期

提示 : 程序员只能做新建和就绪,其他的都由系统来处理

// 创建线程对象 : 新建状态

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];

// 启动线程 : 就绪状态(把线程对象添加到可调度线程池,等待被CPU调度执行)

[thread start];

// sleepForTimeInterval : 使当前线程休眠到指定时长

[NSThread sleepForTimeInterval:1.0];

// sleepUntilDate : 使当前线程休眠到指定日期

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

// 使当前线程强制死亡

[NSThread exit];

线程的属性

//新建状态

NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(demo) object:nil];

// 设置线程对象的name属性 : 标识一个唯一的线程对象,方便跟踪

thread1.name = @"t1";

thread1.threadPriority = 1.0;

// 设置线程对象的优先级 : 浮点数;范围是0.0~1.0;最高是1.0;默认是0.5

// 线程优先级不能决定线程执行的先后顺序,只能决定某个线程有更多的机会被CPU先调度执行完,概率事件

// 注意 : 实际开发中,千万不要设置优先级或者服务器质量,会出现意想不到的问题;使用默认的,让系统自己来处理

// threadPriority : 在目前即将被废弃,使用qualityOfService来替代;

thread1.qualityOfService = NSQualityOfServiceUserInteractive;

// stackSize : 线程占用内存空间大小

NSLog(@"子 %tu",[NSThread currentThread].stackSize / 1024);

多线程的资源共享问题

// 互斥锁 / 同步锁 : 使用了线程同步技术

// 特点 : 可以保证被锁定的代码,同一时间只有一个线程可以访问

// self : 表示互斥锁的参数;互斥锁的参数,又叫做锁对象;

// 锁对象 : 任何继承自NSObject的对象,都可以作为互斥锁的参数;内部有把锁,默认是开启的

// 锁对象必须是全局的对象;self是最方便获取的全局的锁对象

// 局部锁对象是锁不住的,因为每次线程进来之前会新建一把锁

// 提示 : 加锁的事情,不是再客户端操作的;是服务器加锁的,多线程资源共享绝大多数是在服务器发生;

// 提示 : 加锁是牺牲了性能,保证安全.客户端的性能不能轻易牺牲

@synchronized (self)

{

      //需要被锁定的代码

}

参数必须传全局对象 多数传self 

原子属性

使用nonatomic修饰的属性为非原子属性

使用atomic修饰的属性为原子属性

原子属性 : 单写多读

单写多读 : 同一时间只有一个线程可以访问setter方法;但是可以有多个线程访问getter方法

注意 : 原子属性的setter方法是线程安全的,getter方法是线程非安全的

setter方法内部有把自旋锁

自旋锁 :

 看不见的,由系统封装的

可以保证被锁定的代码,同一时间只能有一个线程可以访问

一旦外面的线程,发现代码被自旋锁锁定,外面的线程会以死循环的方式等待开锁

互斥锁 :

可以保证被锁定的代码,同一时间只能有一个线程可以访问

一旦外面的线程,发现代码被互斥锁锁定,外面的线程会进入就绪状态,等待开锁

相关文章

网友评论

      本文标题:多线程01 pthread NSThread 多线程的资源共享问

      本文链接:https://www.haomeiwen.com/subject/serzyttx.html