程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> [並發並行]_[Object-C]_[使用NSMutableArray等非線程安全集合類的注意事項]

[並發並行]_[Object-C]_[使用NSMutableArray等非線程安全集合類的注意事項]

編輯:關於C語言

[並發並行]_[Object-C]_[使用NSMutableArray等非線程安全集合類的注意事項]


 

場景:

1. 開發Mac,iOS程序時,一般都會涉及到多線程開發, 比如工作線程在更新數據模型, 主線程根據數據模型來顯示界面.

比如最常用的NSMutableArray, NSMutableDictionary等, 這類集合在調用讀寫方法時並不是線程安全的,也就是說會出現數據不一致性和崩潰現象.

2. 解決辦法就是使用@syncronized()關鍵字, 有點類似Java.

 

test.cpp

 

//
//  main.c
//  test_sync
//
//  Created by daih on 11/12/15.
//  Copyright (c) 2015 infoworld. All rights reserved.
//

#include 
#import 

#include 
#include pthread.h
#include 
#include 

static int THREADCOUNT = 100;


// 需要多線程測試的類,類裡有集合類型屬性和原始類型屬性.
@interface MyDevice : NSObject
{
    NSMutableArray* usbArray; // 集合類型
    NSInteger usbCount; //原始類型
}

@property(readonly) NSMutableArray* usbArray;

// 原始類型可以設置原子訪問只是保證不會讀髒數據,但是不能保證算數運算的同步.
// 所以還是得加鎖.
@property(readwrite,assign,atomic) NSInteger usbCount;

@end

@implementation MyDevice

@synthesize usbArray;
@synthesize usbCount;

-(id)init
{
    [super init];
    usbArray = [NSMutableArray new];
    usbCount = 0;

    return self;
}

@end

static MyDevice* gDevice = [MyDevice new];
static int gCount = 0;
void* ThreadFunc(void* data)
{
    for (int i = 0; i < 10000; ++i)
    {
        // 每次+1,注意,這裡gDevice.usbCount+1並不是原子操作,所以有可能多個線程的值是一樣的.
        [gDevice setUsbCount:gDevice.usbCount+1];
        // 如果是多線程訪問,讀寫usbArray都需要加鎖.
        @synchronized(gDevice.usbArray)
        {
            [gDevice.usbArray addObject:@(i)];
        }
    }
    ++gCount;
    return NULL;
}

void TestSyncVariable()
{
    for (int i = 0; i < THREADCOUNT; ++i)
    {
        pthread_t t;
        pthread_create(&t,NULL,ThreadFunc,NULL);
        pthread_detach(t);
    }
}

int main(int argc, const char * argv[])
{
    // insert code here...
    CFShow(CFSTR(Hello, World!
));
    TestSyncVariable();
    while (gCount != THREADCOUNT)
    {
        sleep(2);
    }
    std::cout << [gDevice.usbArray count]:  << [gDevice.usbArray count] << std::endl;
    std::cout << gDevice.usbCount:  << gDevice.usbCount << std::endl;
    
    assert(gDevice.usbCount <= [gDevice.usbArray count]);
    assert([gDevice.usbArray count] == THREADCOUNT*10000);
    CFShow(CFSTR(Bye, World!
));
    return 0;
}

輸出:

 

 

Hello, World!
[gDevice.usbArray count]: 1000000
gDevice.usbCount: 999997
Bye, World!
Program ended with exit code: 0

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved