文件读写操作中锁的使用

1、简述
1.1、多线程操作中必然会涉及到锁的概念,使用锁来确保线程安全;
1.2、事实上某些操作,比如数据读取是可以允许多线程同时操作的;
1.3、但写操作不行,数据写入动作必须是同步的,否则会出现数据错误;
1.4、如果读、写操作动作同时发生,并且多线程并发操作时该如何处理?
1.5、通过普通加锁实现线程同步,这样线程是安全了,但影响了读取的效率;
1.6、基本思路是
1.6.1、允许读取操作多线程并发进行;
1.6.2、写入操作只能单个线程同步进行;
1.7、常用的解决方案有两个
1.7.1、pthread_rwlock
1.7.2、dispatch_barrier_async

2、代码示例
2.1、pthread_rwlock

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#import "ViewController.h"
#import <pthread.h>
@interface ViewController()
{
    pthread_rwlock_t    _rwlock;
}
@end
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    pthread_rwlock_init(&_rwlock, NULL);
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self read];
        });
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self write];
        });
    }
}
 
- (void)read
{
    pthread_rwlock_rdlock(&_rwlock);
    sleep(1);
    NSLog(@"read...");
    pthread_rwlock_unlock(&_rwlock);
}
 
- (void)write
{
    pthread_rwlock_wrlock(&_rwlock);
    sleep(1);
    NSLog(@"write...");
    pthread_rwlock_unlock(&_rwlock);
}
@end

执行结果:

2018-11-28 14:40:42.959452+0800 MultiThread[11616:2172598] read...
2018-11-28 14:40:43.964333+0800 MultiThread[11616:2172597] write...
2018-11-28 14:40:44.969387+0800 MultiThread[11616:2172599] read...
2018-11-28 14:40:45.974642+0800 MultiThread[11616:2172673] write...
2018-11-28 14:40:46.975541+0800 MultiThread[11616:2172674] read...
2018-11-28 14:40:47.979765+0800 MultiThread[11616:2172675] write...
2018-11-28 14:40:48.982189+0800 MultiThread[11616:2172676] read...
2018-11-28 14:40:49.986234+0800 MultiThread[11616:2172677] write...
2018-11-28 14:40:50.990627+0800 MultiThread[11616:2172678] read...
2018-11-28 14:40:51.995698+0800 MultiThread[11616:2172679] write...
2018-11-28 14:40:53.000450+0800 MultiThread[11616:2172680] read...
2018-11-28 14:40:54.004271+0800 MultiThread[11616:2172681] write...
2018-11-28 14:40:55.007637+0800 MultiThread[11616:2172682] read...
2018-11-28 14:40:56.010467+0800 MultiThread[11616:2172683] write...
2018-11-28 14:40:57.016078+0800 MultiThread[11616:2172684] read...
2018-11-28 14:40:58.018431+0800 MultiThread[11616:2172685] write...
2018-11-28 14:40:59.024275+0800 MultiThread[11616:2172687] write...
2018-11-28 14:41:00.029617+0800 MultiThread[11616:2172686] read...
2018-11-28 14:41:00.029645+0800 MultiThread[11616:2172688] read...
2018-11-28 14:41:01.034141+0800 MultiThread[11616:2172689] write...

2.2、dispatch_barrier_asyn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#import "ViewController.h"
#import <pthread.h>
@interface ViewController()
{
    dispatch_queue_t    _queue;
}
@end
@implementation ViewController
 
- (void)viewDidLoad
{
    [super viewDidLoad];
    _queue = dispatch_queue_create("rw_queue", DISPATCH_QUEUE_CONCURRENT);
    for (int i = 0; i < 10; i++) {
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self read];
        });
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            [self write];
        });
    }
}
 
- (void)read
{
    dispatch_async(_queue, ^{
        sleep(1);
        NSLog(@"read...");
    });
}
 
- (void)write
{
    dispatch_barrier_async(_queue, ^{
        sleep(1);
        NSLog(@"write...");
    });
}
@end

执行结果:

2018-11-28 14:58:53.655607+0800 MultiThread[11850:2327033] read...
2018-11-28 14:58:53.655634+0800 MultiThread[11850:2327049] read...
2018-11-28 14:58:54.658272+0800 MultiThread[11850:2327033] write...
2018-11-28 14:58:55.662524+0800 MultiThread[11850:2327033] write...
2018-11-28 14:58:56.664781+0800 MultiThread[11850:2327033] read...
2018-11-28 14:58:56.664781+0800 MultiThread[11850:2327035] read...
2018-11-28 14:58:56.664781+0800 MultiThread[11850:2327049] read...
2018-11-28 14:58:57.669830+0800 MultiThread[11850:2327049] write...
2018-11-28 14:58:58.674269+0800 MultiThread[11850:2327049] write...
2018-11-28 14:58:59.678279+0800 MultiThread[11850:2327049] write...
2018-11-28 14:59:00.682485+0800 MultiThread[11850:2327049] read...
2018-11-28 14:59:01.687585+0800 MultiThread[11850:2327049] write...
2018-11-28 14:59:02.693012+0800 MultiThread[11850:2327049] read...
2018-11-28 14:59:03.697764+0800 MultiThread[11850:2327049] write...
2018-11-28 14:59:04.702663+0800 MultiThread[11850:2327049] read...
2018-11-28 14:59:05.705765+0800 MultiThread[11850:2327049] write...
2018-11-28 14:59:06.709361+0800 MultiThread[11850:2327049] read...
2018-11-28 14:59:07.710608+0800 MultiThread[11850:2327049] write...
2018-11-28 14:59:08.715003+0800 MultiThread[11850:2327049] read...
2018-11-28 14:59:09.720101+0800 MultiThread[11850:2327049] write...

3、结论:在打印read…时可以看到多个read连续打印时时间基本上是相同的,但write打印是相隔1秒的;

Leave a Reply