经典同步问题1:生产者-消费者问题
问题描述:
有一组生产者的线程和一组消费者的线程共享一个初始为空,大小为n的缓冲区,如果缓冲区未满,那么生产者就可以把生产的放进缓冲区里,如果缓冲区不空,那么消费者就可以从缓冲区取出来消费; 问题分析: * 关系分析:生产者和消费者对缓冲区的互斥访问是互斥关系,同时生产者和消费者又是一个协作的关系,之后生产者生产了之后,消费者才可以消费,他们是同步关系。
下面就是用oc的解决办法。我们用到的NSCondition在这里介绍一下。
NSCondition就是一个lock,是一个线程锁。当你NSCondition wait 之后,他会这个线程会处于等待状态。如果这个NSCondition在其他地方执行signal之后。wait 的线程会继续执行。
下面上代码。来看一下我的代码吧
//
// ViewController.m
// condition
//
// Created by XD on 15/7/23.
// Copyright (c) 2015年 XD. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
<
UITableViewDataSource,
UITableViewDelegate
>
@property (strong ,nonatomic)NSCondition *condition;
@property (strong ) NSMutableArray *taskArr;
@property (weak, nonatomic) IBOutlet UITableView *tanleview;
@end
static NSString *identifier = @"identifier";
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.taskArr = [[NSMutableArray alloc]initWithCapacity:42];
self.condition = [[NSCondition alloc]init];
[self.tanleview registerClass:[UITableViewCell class] forCellReuseIdentifier:identifier];
//创建消费者队列
dispatch_queue_t coustomerQueue = dispatch_queue_create("customerQueue", NULL);
dispatch_async(coustomerQueue, ^{
//消费者会一直去销毁东西
while (1) {
//这里加锁是必要的
[self.condition lock];
//当产品队列是空时 线程等待
while ([self.taskArr count] == 0) {
[self.condition wait];
}
//取出产品产品
id task = [self.taskArr firstObject];
if (task) {
//销毁产品
[self.taskArr removeObject:task];
NSLog(@"customer eat task count = %lu",(unsigned long)[self.taskArr count]);
}
[self.condition unlock];
}
});
//创建一个生产者队列
dispatch_queue_t factoryQueue = dispatch_queue_create("factoryQueue", NULL);
//生产者会一直尝试去生产产品
dispatch_async(factoryQueue, ^{
while (1) {
[self.condition lock];
[self.taskArr addObject:@"a"];
NSLog(@"factory create task count = %lu",(unsigned long)[self.taskArr count]);
//生产完毕后会去告诉等待的线程
[self.condition signal];
[self.condition unlock];
}
});
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:@"%zd",indexPath.row];
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end