iphone多線程練習之火車售票模擬

#import <UIKit/UIKit.h>

@interface LeeAppDelegate : UIResponder <UIApplicationDelegate>{
    int tickets;
    int count;
    
    NSThread *ticketsThreadOne;
    NSThread *ticketsThreadTwo;
    NSCondition *ticketsCondition;
}

@property (strong, nonatomic) UIWindow *window;

@end

建立一個最簡單的ios空工程,在代理類中加入兩個線程對象(NSThread),和一個用於同步的信號量(NSCondition)

然後再實現文件中,程序加載函數中初始化車票數(tickets)10張,線程1和線程2的執行函數爲run。爲防止線程爭奪臨界區資源,進入run函數後要加鎖Lock,然後本線程執行完一次run函數後要對資源解鎖,讓另外的線程訪問臨界區資源。爲了便於觀察,讓線程執行時睡眠一段時間。代碼:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    tickets = 10;
    count = 0;
    
    ticketsCondition = [[NSCondition alloc]init];
    
    ticketsThreadOne = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadOne setName:@"Thread-1"];
    [ticketsThreadOne start];
    
    ticketsThreadTwo = [[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];
    [ticketsThreadTwo setName:@"Thread-2"];
    [ticketsThreadTwo start];
    
    
    
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

-(void)run{
    while (TRUE) {
        [ticketsCondition lock];
        if (tickets > 0) {
            [NSThread sleepForTimeInterval:2];
            count = 10 - tickets;
            NSLog(@"當前票數:%d,售出%d,線程名%@",tickets,count,[[NSThread currentThread]name]);
            tickets--;
        }
        else{
            break;
        }
        [ticketsCondition unlock];
    }
}
運行,輸出結果正常,兩個線程配合的很好,爲了更好的學習多線程,可以把加鎖和解鎖的兩條語句去掉,然後運行,發現連個線程出現了混亂。


主要原因是多線程中每個線程都有自己的數據區,當線程1開始執行時,先把主線程數據複製到自己的數據區中,然後操作的是自己數據區的內容,而不直接修改主線程中的數據,假設開始車票10張,線程1數據區拷貝主線程數據也爲10張,當線程1執行到sleep語句時,就被掛起。這時候線程2開始運行,線程2也有自己的數據區,把主線程數據區的內容拷貝到自己的數據區中,因爲主線程這時候的票數還爲10,所以線程2的數據區拷貝也爲10張。當線程2運行到sleep語句時,線程2也被掛起。線程1等待2秒後開始運行,賣出一張票,把自己數據區的票數改爲9,然後返回主線程,主線程修改自己的數據區票數爲9.線程2等待2秒後也開始執買票動作,賣出去一張票,修改數據區內容爲9,然後返回主線程,修改主線程數據爲9.。這樣我們就發現了問題,兩個線程賣出去了兩張票,而總票數才少了一張,這樣就會出錯了。

避免這樣的辦法就是加鎖,當線程1要修改臨界區數據時就把數據加上鎖,意思是自己在執行數據修改時,不允許其他線程修改數據,這樣就確保了程序正常運行。

具體再深入學習,那就要看操作系統方面的關於多線程的知識了,這只是個開頭。大學操作系統課程沒好好學,當時不知道有什麼用,現在知道了用處那麼大,悲催啊,該快好好學,呵呵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章