文档章节

第01天多线程网络:(09):线程安全

宇鸿165
 宇鸿165
发布于 2017/04/15 09:53
字数 1117
阅读 6
收藏 0

#####一、线程安全


 线程安全隐患的问题
 例子1:
     存钱-取钱 余额(1000)
     同时时间操作
     存1000 = 1000 + 1000 = 2000
     取 1000 - 500 = 500
     余额 500 // 安全隐患出现的问题
例子2:
 卖票1 卖票2 票数(1000)
    卖票1 卖出1张 = 1000 - 1;
    卖票2 卖出1张 = 1000 - 1;
    余 : 999 // 安全隐患出现的问题
 
 安全隐患解决办法 : 添加互斥锁 (加锁lock  解锁uniock)
 每个线程进行访问一个资源的时候 进行一个加锁操作
 线程A 进行操作 线程B 是不可以访问的 因为 线程A已经加锁了
 
 例子 : 上厕所


  • 1.互斥锁的创建@synchronized (一般把控制器作为全局唯一的) {// 锁里面的代码...}
 互斥锁使用格式
 @synchronized(锁对象) { // 需要锁定的代码  }
 注意:锁定1份代码只用1把锁,用多把锁是无效的
 
 互斥锁的优缺点
 优点:能有效防止因多线程抢夺资源造成的数据安全问题
 缺点:需要消耗大量的CPU资源
 
 互斥锁的使用前提:多条线程抢夺同一块资源
 
 相关专业术语:线程同步
 线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务)
 互斥锁,就是使用了线程同步技术

使用售票例子来说明 code


/**
 线程安全隐患的问题
 例子1:
     存钱-取钱 余额(1000)
     同时时间操作
     存1000 = 1000 + 1000 = 2000
     取 1000 - 500 = 500
     余额 500 // 安全隐患出现的问题
例子2:
 卖票1 卖票2 票数(1000)
    卖票1 卖出1张 = 1000 - 1;
    卖票2 卖出1张 = 1000 - 1;
    余 : 999 // 安全隐患出现的问题
 
 安全隐患解决办法 : 添加互斥锁 (加锁lock  解锁uniock)
 每个线程进行访问一个资源的时候 进行一个加锁操作
 线程A 进行操作 线程B 是不可以访问的 因为 线程A已经加锁了
 
 例子 : 上厕所
 
 
 互斥锁使用格式
 @synchronized(锁对象) { // 需要锁定的代码  }
 注意:锁定1份代码只用1把锁,用多把锁是无效的
 
 互斥锁的优缺点
 优点:能有效防止因多线程抢夺资源造成的数据安全问题
 缺点:需要消耗大量的CPU资源
 
 互斥锁的使用前提:多条线程抢夺同一块资源
 
 相关专业术语:线程同步
 线程同步的意思是:多条线程在同一条线上执行(按顺序地执行任务)
 互斥锁,就是使用了线程同步技术
 
 */

#import "ViewController.h"

@interface ViewController ()

/** 售票员 A */
@property(nonatomic) NSThread *threadA;
/** 售票员 B */
@property(nonatomic) NSThread *threadB;
/** 售票员 C */
@property(nonatomic) NSThread *threadC;

// 有没有余票
@property(nonatomic,assign) NSInteger totalCount;

@end

@implementation ViewController

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 设置总票数
    self.totalCount = 100;
    
    self.threadA  = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
    self.threadB  = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
    self.threadC  = [[NSThread alloc]initWithTarget:self selector:@selector(saleTicket) object:nil];
    
    self.threadA.name = @"售票员A";
    self.threadB.name = @"售票员B";
    self.threadC.name = @"售票员C";
    
    // 启动线程
    [self.threadA start];
    [self.threadB start];
    [self.threadC start];
#pragma mark 互斥锁
    /*
     锁必须是全局唯一的
    @synchronized (一般把控制器作为全局唯一的) {
        // 锁里面的代码...
    }
     */
    
    // 1.注意加锁的位置
    // 2.注意加锁的前提条件,多线程共享同一块资源
    // 3.注意加锁是需要付出代价的。需要耗费性能的
    // 4.加锁的结果: 线程同步 (排队)
 
}

- (void)saleTicket
{
    // 如果加到外面 1个售票员就卖光了
        // 死循环
        while (1) {
            
//            @synchronized([[NSObject alloc]init]){} // 错误写法  [[NSObject alloc]init] 不是全局唯一的
            @synchronized (self) {
            // 线程1
            // 线程2
            // 线程3
            NSInteger count = self.totalCount;  // 记录总票数
            if (count > 0) {

                for (NSInteger i = 0 ; i < 1000000; i++) {
                    /*
                     // 这里可以模拟一个耗时操作 来查看同步的明显效果
                     // 使用for 循环 空转
                     2017-04-20 14:19:21.363 09.线程安全[1820:178672] 售票员B卖出去了一张票,还剩下99张票
                     2017-04-20 14:19:21.363 09.线程安全[1820:178673] 售票员C卖出去了一张票,还剩下99张票
                     2017-04-20 14:19:21.363 09.线程安全[1820:178671] 售票员A卖出去了一张票,还剩下99张票
                     */
                }
                self.totalCount = count - 1;
                // 卖出去一张票
                NSLog(@"%@卖出去了一张票,还剩下%zd张票",[NSThread currentThread].name,self.totalCount);
            }
            else
            {
                NSLog(@"不要回家上班了");
                // 退出循环
                break;
            }
            
        }
    }

    
}


@end

© 著作权归作者所有

宇鸿165
粉丝 1
博文 919
码字总数 368963
作品 0
广州
私信 提问
JavaScript 30天每日效果图

JavaScript 30天每日效果图 在Github上看到了wesbos的一个Javascript30天挑战的repo,旨在使用纯JS来进行练习,不允许使用任何其他的库和框架,该挑战共30天,我会在这里复现这30天遇到的挑战...

黎跃春
2017/07/19
0
0
java学习计划

源于传智播客毕向东老师的教学计划: day01-01-基本常识 day01-02-Java的跨平台性 day01-03-Java环境搭建(安装) day01-04-Java环境搭建(环境变量配置) day01-05-Java环境搭建(环境变量配置技...

Bony
2016/05/14
60
0
理解 Python 中的多线程

我们将会看到一些在 Python 中使用线程的实例和如何避免线程之间的竞争。 你应当将下边的例子运行多次,以便可以注意到线程是不可预测的和线程每次运行出的不同结果。声明:从这里开始忘掉你...

大数据之路
2013/11/27
11.4K
0
iOS开发之多线程技术(NSThread、OperationQueue、GCD)

在前面的博客中如果用到了异步请求的话,也是用到的第三方的东西,没有正儿八经的用过iOS中多线程的东西。其实多线程的东西还是蛮重要的,如果对于之前学过操作系统的小伙伴来说,理解多线程...

小近
2014/11/13
886
1
Java设计模式之单例模式(七种写法)

第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: 第二种,懒汉式,lazy初始化,线程安全: 优点:第一次调用才初始化,避免内存浪费。 缺点:必须加锁 synchronized 才能保证单例...

SiberianDante
2018/01/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OpenStack 简介和几种安装方式总结

OpenStack :是一个由NASA和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenSta...

小海bug
昨天
5
0
DDD(五)

1、引言 之前学习了解了DDD中实体这一概念,那么接下来需要了解的就是值对象、唯一标识。值对象,值就是数字1、2、3,字符串“1”,“2”,“3”,值时对象的特征,对象是一个事物的具体描述...

MrYuZixian
昨天
6
0
数据库中间件MyCat

什么是MyCat? 查看官网的介绍是这样说的 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务、ACID、可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵...

沉浮_
昨天
6
0
解决Mac下VSCode打开zsh乱码

1.乱码问题 iTerm2终端使用Zsh,并且配置Zsh主题,该主题主题需要安装字体来支持箭头效果,在iTerm2中设置这个字体,但是VSCode里这个箭头还是显示乱码。 iTerm2展示如下: VSCode展示如下: 2...

HelloDeveloper
昨天
7
0
常用物流快递单号查询接口种类及对接方法

目前快递查询接口有两种方式可以对接,一是和顺丰、圆通、中通、天天、韵达、德邦这些快递公司一一对接接口,二是和快递鸟这样第三方集成接口一次性对接多家常用快递。第一种耗费时间长,但是...

程序的小猿
昨天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部