线程
- 一个进程要想执行任务, 就必须开启线程.
- 一个线程同一时间只能执行一个任务(线程内部是串行的).
多线程
- CPU 通过操控多个线程切换, 并行执行任务!
- 提高效率;
- 线程开销, 耗性能, 发热耗电;
主线程
- UI线程, 刷新UI 界面, 处理点击事件;
- 防止线程阻塞.
First Header | Second Header |
---|---|
pthread | C |
NSThread | OC |
GCD | C |
NSOperation | C |
-
线程的状态
runnable, running, blocked(sleep), dead
[NSThread exit]; [NSThread sleepForTimeInterval:2.f];
-
Pthread
/** POSIX 多线程开发框架 pthread_t _Nullable *restrict _Nonnull: 指向线程代号的指针 const pthread_attr_t *restrict _Nullable: 线程的属性 void * _Nullable (* _Nonnull)(void * _Nullable): 指向函数的指针 void *restrict _Nullable: 传递给该函数的参数 返回值: - 如果是0, 标识正确 - 非0, 错误 void * (*) (void *) 返回值 函数指针 id ARC 中用到 C 语言中数据类型, 需要进行桥接转换; __bridge (需要设置 free ) MRC 不需要 */ pthread_t threadId; NSString *str = @"hello world"; int result = pthread_create(&threadId, NULL, &demo, (__bridge void *)(str)); if (result == 0) { NSLog(@"success"); } else { NSLog(@"error"); }
-
NSThread
- (void)nsthreadDemo1 { NSLog(@"_______1________"); // 1. 创建线程(子线程) NSThread *thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(thread1Method:) object:@"obj"]; // 开启线程 [thread1 start]; // 2. 不用手动开启 [NSThread detachNewThreadWithBlock:^{ [self thread1Method:@"block"]; [self performSelector:@selector(thread1Method:) withObject:@"perform"]; }]; [NSThread detachNewThreadSelector:@selector(thread1Method:) toTarget:self withObject:@"target"]; // 3. map // 默认当前线程 // [self performSelector:@selector(thread1Method:) withObject:@"perform"]; // 子线程 [self performSelectorInBackground:@selector(thread1Method:) withObject:@"background"]; NSLog(@"_______2________"); }
-
互斥锁(
synchronized
)- 保证代码在同一时间内, 只能执行一行代码!
- 使用范围尽量小;
- 参数应为线程全局变量(保证锁唯一性)! (若为线程私有变量, 加锁无效)
自旋锁 互斥锁 保证线程安全 保证线程安全 耗性能 耗性能 被锁在外面的线程, 用死循环的方式等待解锁 被锁在外面的线程, 进入休眠状态, 待锁打开后被唤醒 read 不会加锁, write 回加锁 read, write 都会加锁 @synchronized(self){ if (self.ticket > 0) { self.ticket--; NSLog(@"left = %d --- %@", self.ticket, [NSThread currentThread]); }else{ NSLog(@"sale out -- %@", [NSThread currentThread]); break; } }
atomic: 原子性
修饰的属性, 默认有一个自旋锁(单线程写, 多线程读);
保证多个线程访问这个对象的时候, 同一时间只有一个线程能够执行!
先把文件保存在一个临时文件中, 等全部写入之后, 再改名字![@"" writeToFile:<#(nonnull NSString *)#> atomically:<#(BOOL)#> encoding:<#(NSStringEncoding)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>];
nonatomic: 非原子性
线程安全: 在多个线程同时进行读写操作时, 任然能保证数据安全. 所以约定在主线程进行UI 刷新, 是为了保证线程安全
网友评论