#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要修改臨界區數據時就把數據加上鎖,意思是自己在執行數據修改時,不允許其他線程修改數據,這樣就確保了程序正常運行。
具體再深入學習,那就要看操作系統方面的關於多線程的知識了,這只是個開頭。大學操作系統課程沒好好學,當時不知道有什麼用,現在知道了用處那麼大,悲催啊,該快好好學,呵呵。