为了保证线程安全,不会因为多个线程访问造成资源抢夺,出现的运行结果的偏差问题,我们需要使用到线程同步技术,最常用的就是 @synchronized互斥锁(同步锁)、NSLock、dispatch_semaphore、原子锁等。

使用方法:

一、

@synchronized(实例化对象){

要加锁的代码

注:实例化对象要保证唯一性,一般使用self当前类对象。

和下面的信号量方式相比,性能不是很好。

二、

dispatch_semaphore:

dispatch_semaphore是GCD用来同步的一种方式,是使用信号量来控制线程是继续等待,还是继续执行下面的代码。

    dispatch_semaphore_t signal = dispatch_semaphore_create(1);    //传入的参数为long,输出一个dispatch_semaphore_t类型且值为
value的信号量。值得注意的是,这里的传入的参数value必须大于或等于0,否则dispatch_semaphore_create会返回NULL
    dispatch_time_t overTime = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);  //超时时间,线程加锁之后等待的时间

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_semaphore_wait(signal, overTime); //这个函数会使传入的信号量dsema的值减1;这个函数的作用是这样的,如果dsema信号量的值大于0,
该函数所处线程就继续执行下面的语句,并且将信号量的值减1;如果desema的值为0,那么这个函数就
阻塞当前线程等待timeout(注意timeout的类型为dispatch_time_t,不能直接传入整形或float
型数),如果等待的期间desema的值被dispatch_semaphore_signal函数加1了,且该函数
(即dispatch_semaphore_wait)所处线程获得了信号量,那么就继续向下执行并将信号量减1。
如果等待期间没有获取到信号量或者信号量的值一直为0,那么等到timeout时,其所处线程自动执行其后语句。
NSLog(@"需要线程同步的操作1 开始");
sleep(2);
NSLog(@"需要线程同步的操作1 结束");
dispatch_semaphore_signal(signal); //这个函数会使传入的信号量的值加1;
}); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
dispatch_semaphore_wait(signal, overTime);
NSLog(@"需要线程同步的操作2");
dispatch_semaphore_signal(signal);
});

 

三、

NSLock:

    NSLock *lock = [[NSLock alloc] init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//[lock lock];
[lock lockBeforeDate:[NSDate date]];
NSLog(@"需要线程同步的操作1 开始");
sleep(2);
NSLog(@"需要线程同步的操作1 结束");
[lock unlock]; }); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
sleep(1);
if ([lock tryLock]) {//尝试获取锁,如果获取不到返回NO,不会阻塞该线程
NSLog(@"锁可用的操作");
[lock unlock];
}else{
NSLog(@"锁不可用的操作");
} NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:3];
if ([lock lockBeforeDate:date]) {//尝试在未来的3s内获取锁,并阻塞该线程,如果3s内获取不到恢复线程, 返回NO,不会阻塞该线程
NSLog(@"没有超时,获得锁");
[lock unlock];
}else{
NSLog(@"超时,没有获得锁");
} });

NSLock是Cocoa提供给我们最基本的锁对象,这也是我们经常所使用的,除lock和unlock方法外,NSLock还提供了tryLock和lockBeforeDate:两个方法,前一个方法会尝试加锁,如果锁不可用(已经被锁住),刚并不会阻塞线程,并返回NO。lockBeforeDate:方法会在所指定Date之前尝试加锁,如果在指定时间之前都不能加锁,则返回NO。

四、单例模式的线程安全问题:

+(AccountManager *)sharedManager

{

static AccountManager *sharedAccountManagerInstance = nil;

static dispatch_once_t predicate; dispatch_once(&predicate, ^{

sharedAccountManagerInstance = [[self alloc] init];

});

return sharedAccountManagerInstance;

}

在方法中先声明了一个实例,并初始化为nil,前面的static关键字可以保证只执行一次为nil的操作。dispatch_once_t是多线程中的,保证只执行一次。dispatch_once这个函数用于检查该代码块是否已经被调用过,通过它不仅可以保证块里面初始化的代码仅被运行一次,还能保证线程的安全。

访问单例的成员变量、静态变量、进行i/o操作应该要考虑线程安全问题。

iOS中的线程安全问题的更多相关文章

  1. 浅谈利用同步机制解决Java中的线程安全问题

    我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...

  2. java设计模式--解决单例设计模式中懒汉式线程安全问题

    首先写个单例,懒汉模式: public class SingleDemo { private static SingleDemo s = null; private SingleDemo(){} pu ...

  3. 逐步理解Java中的线程安全问题

    什么是Java的线程安全问题? 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读/写完,其他线程才可使用.不会出现数据不一致或者数据 ...

  4. JUC之集合中的线程安全问题

    集合线程安全问题 JDK Version:9 首先说下集合线程安全是什么:当多个线程对同一个集合进行添加和查询的时候,出现异常错误. 复现例子: package com.JUC; import jav ...

  5. Linux/Unix编程中的线程安全问题【转】

    转自:http://blog.csdn.net/zhengzhoudaxue2/article/details/6432984 在目前的计算机科学中,线程是操作系统调度的最小单元,进程是资源分配的最小 ...

  6. iOS中保证线程安全的几种方式与性能对比

    来源:景铭巴巴 链接:http://www.jianshu.com/p/938d68ed832c 一.前言 前段时间看了几个开源项目,发现他们保持线程同步的方式各不相同,有@synchronized. ...

  7. stl空间配置器线程安全问题补充

    摘要 在上一篇博客<STL空间配置器那点事>简单介绍了空间配置器的基本实现 两级空间配置器处理,一级相关细节问题,同时简单描述了STL各组件之间的关系以及设计到的设计模式等. 在最后,又关 ...

  8. (2.1)servlet线程安全问题

    本文参考链接:http://www.yesky.com/334/1951334.shtml 摘 要:介绍了Servlet多线程机制,通过一个实例并结合Java 的内存模型说明引起Servlet线程不安 ...

  9. servlet开发(二)之servlet的线程安全问题

    之所以考虑线程安全问题,是因为引入了多线程.多线程指的是这个程序(一个进程)运行时产生了不止一个线程.如果不考虑多线程的话,程序执行只有一条路径,就像人在敲代码的时候只能敲代码,不能戴上耳机听歌.引入 ...

随机推荐

  1. HTML中图像代替提交按钮

    1. 用图像代替提交按钮 当只有一个提交按钮的时候 ,可以简单的实现,不用添加事件函数,代码是: <input type = "image"' name = ".. ...

  2. NYOJ题目28大数阶乘

    -------------------------------------祭出BigInteger AC代码: import java.math.BigInteger; import java.uti ...

  3. [BI项目记]-对项目文件进行规划

    BI项目中会有很多不同种类的项目,此篇会对这些项目进行一个总结,并且在TFS中进行分类. 根据笔者对BI项目的经验和理解,主要将BI项目中的项目类型进行如下分类: DB脚本 DB脚本是BI项目中重要的 ...

  4. 【Cocos2d-x for WP8 学习整理】(1)创建一个新项目

    喜大普奔                         10.1假期之前看到了一个很振奋的消息,就是随着Cocos2d-x 2.2的发布,WP8/WIN8有史以来第一次的合并到主版本了. 之前 V2 ...

  5. PHP运行模式

    1.运行模式 关于PHP目前比较常见的五大运行模式: 1)CGI(通用网关接口 / Common Gateway Interface) 2)FastCGI(常驻型CGI / Long-Live CGI ...

  6. python 线程之 数据同步 Queue

    Queue:将数据从一个线程发往另外一个线程比较通用的方式是使用queue模块的Queue类 1, 首先创建一个Queue模块的对象,创建Queue对象可以传递maxsize也可以不传递 2. 使用对 ...

  7. 分享一下自己用c++写的小地图

    http://www.unrealchina.com/forum.php?mod=viewthread&tid=451&extra=&from=portal&page= ...

  8. CSS3 justify 文本两端对齐

    浏览器参照基准:Firefox4 and Later, Chrome5 and Later, Safari5 and Later, Opera10.53 and Later, IE5.5 and La ...

  9. MongoDB-C#驱动帮助

    查增改删 链接字符串 MongoDB超管+(admin) 单独库用户不加 static string mongoR = string.Format("mongodb://{0}(admin) ...

  10. gitlab 创建SSH Keys 报500错

    gitlab 创建SSH Keys 报500错 看了一下日志 root@322323:/home/git/gitlab/log# cat production.log Errno::ENOMEM (C ...