多執行緒程式設計同步問題
阿新 • • 發佈:2019-01-03
實現機制有:1 互斥鎖 2 訊號量 3 條件變數
一、 為什麼要用多執行緒技術?
1、避免阻塞,大家知道,單個程序只有一個主執行緒,當主執行緒阻塞的時候,整個程序也就阻塞了,無法再去做其它的一些功能了。
2、避免CPU空轉,應用程式經常會涉及到RPC,資料庫訪問,磁碟IO等操作,這些操作的速度比CPU慢很多,而在等待這些響應時,CPU卻不能去處理新的請求,導致這種單執行緒的應用程式效能很差。
3、提升效率,一個程序要獨立擁有4GB的虛擬地址空間,而多個執行緒可以共享同一地址空間,執行緒的切換比程序的切換要快得多。
下面給出個多執行緒程式,一個最簡單的模擬售票系統,程式碼如下:
- #include <stdio.h>
- #include <pthread.h>
- void *ticketsell1(void *);
- void *ticketsell2(void *);
- int tickets = 20;
- int main()
- {
- pthread_t id1,id2;
- int error;
- error = pthread_create(&id1, NULL, ticketsell1, NULL);
- if(error != 0)
- {
- printf("pthread is not created!\n");
- return
- }
- error = pthread_create(&id2, NULL, ticketsell2, NULL);
- if(error != 0)
- {
- printf("pthread is not created!\n");
- return -1;
- }
- pthread_join(id1,NULL);
- pthread_join(id2,NULL);
- return 0;
- }
- void *ticketsell1(void *arg)
- {
- while(1)
- {
- if(tickets > 0)
- {
- // usleep(1000);
- printf("ticketse1 sells ticket:%d\n",tickets--);
- }
- else
- {
- break;
- }
- }
- return (void *)0;
- }
- void *ticketsell2(void *arg)
- {
- while(1)
- {
- if(tickets > 0)
- {
- // usleep(1000);
- printf("ticketse2 sells ticket:%d\n",tickets--);
- }
- else
- {
- break;
- }
- }
- return (void *)0;
- }
執行結果如下:
- [email protected]:~/qiang/mthread$ ./mthread1
- ticketse2 sells ticket:20
- ticketse2 sells ticket:19
- ticketse2 sells ticket:18
- ticketse2 sells ticket:17
- ticketse2 sells ticket:16
- ticketse2 sells ticket:15
- ticketse2 sells ticket:14
- ticketse2 sells ticket:13
- ticketse2 sells ticket:12
- ticketse2 sells ticket:11
- ticketse2 sells ticket:10
- ticketse2 sells ticket:9
- ticketse2 sells ticket:8
- ticketse2 sells ticket:7
- ticketse2 sells ticket:6
- ticketse2 sells ticket:4
- ticketse2 sells ticket:3
- ticketse2 sells ticket:2
- ticketse2 sells ticket:1
- ticketse1 sells ticket:5
看到結果,我們發現時能正常賣票的,一部分連續是sel2,另一部分是ticketsel1;
此時,其實存在一個隱含的問題,就是執行緒間的切換,在單CPU系統中,CPU是有時間片時間,時間片到了,就要執行其它的執行緒,假設thread1執行到if裡面,但在printf執行前發生了執行緒切換,那麼會發生什麼呢?我們在這裡用usleep函式(放開程式中的usleep註釋行)進行強制模擬切換;
我們看看結果:
- [email protected]:~/qiang/mthread$ gcc -o mthread1 mthread1.c -lpthread
- [email protected]:~/qiang/mthread$ ./mthread1
- ticketse2 sells ticket:20
- ticketse1 sells ticket:19
- ticketse2 sells ticket:18
- ticketse1 sells ticket:17
- ticketse2 sells ticket:16
- ticketse1 sells ticket:15
- ticketse2 sells ticket:14
- ticketse1 sells ticket:13
- ticketse2 sells ticket:12
- ticketse1 sells ticket:11
- ticketse2 sells ticket:10
- ticketse1 sells ticket:9
- ticketse2 sells ticket:8
- ticketse1 sells ticket:7
- ticketse2 sells ticket:6
- ticketse1 sells ticket:5
- ticketse2 sells ticket:4
- ticketse1 sells ticket:3
- ticketse1 sells ticket:2
- ticketse2 sells ticket:1
- ticketse1 sells ticket:0
- [email protected]:~/qiang/mthread$
執行程式發現竟然有0號票被賣出了,這顯然是錯誤的!當thread1的if裡面發生執行緒切換時,thread2得到執行,把最後一張票賣了,此時thread1恢復執行,結果賣出了0號票,這裡我們需要的是火車票的票數資料對於所有執行緒而言是同步的,所以就要用到執行緒同步技術了。
三、 使用多執行緒的同步與互斥
1、多執行緒的同步方式有很多種,例如互斥鎖,條件變數,訊號量,讀寫鎖。先看看互斥鎖如何解決多執行緒之間的同步問題。程式用互斥鎖後如下:
- #include <stdio.h>
- #include <pthread.h>
- void *ticketsell1(void *);
- void *ticketsell2(void *);
- int tickets = 20;
- pthread_mutex_t mutex;
- int main()
- {
- pthread_t id1,id2;
- pthread_mutex_init(&mutex, NULL);//
- int error;
- error = pthread_create(&id1, NULL, ticketsell1, NULL);
- if(error != 0)
- {
- printf("pthread is not created!\n");
- return -1;
- }
- error = pthread_create(&id2, NULL, ticketsell2, NULL);
- if(error != 0)
- {
- printf("pthread is not created!\n");
- return -1;
- }
- pthread_join(id1,NULL);
- pthread_join(id2,NULL);
- return 0;
- }
- void *ticketsell1(void *arg)
- {
- while(1)
- {
-
相關推薦
no