gogo专业大尺度亚洲高清人体,美女张开双腿让男生桶,亚洲av无码一区二区三区鸳鸯影院,久久久久国产精品人妻

當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > 為什么需要同步?

為什么需要同步? 時(shí)間:2018-09-26      來源:未知

1. 為什么需要同步?

上面的圖是從《高級編程》中截的圖,雖然它是針對線程的,但是這里要說明,不僅僅線程要考慮這個(gè)問題,只要涉及到并發(fā)的程序,都要考慮同步。比如多進(jìn)程共享內(nèi)存,比如某個(gè)驅(qū)動會同時(shí)被打開,而且會被幾個(gè)進(jìn)程同時(shí)修改驅(qū)動中的值或者寄存器......

原理上都是一樣的,多線程并發(fā)訪問是一定要注意的,因?yàn)橥贿M(jìn)程的多個(gè)線程本身就共享進(jìn)程資源或者說變量的內(nèi)存。就拿上圖來說,我們對i變量的值+1操作,那么這個(gè)簡簡單單的+1操作真正到了CPU上會怎么執(zhí)行呢?通常分為3步:

(1) 從內(nèi)存單元讀入寄存器

(2) 在寄存器上進(jìn)行變量值增加

(3) 把新的值寫回內(nèi)存單元

這就導(dǎo)致了上圖的問題,A線程在把i從內(nèi)存讀入寄存器改變過程中(還沒寫回到內(nèi)存),B線程也對i做了同樣操作,以至于后結(jié)果就是讀入的都是5,寫入的都是6,那么本來我們是要對i增加2次的,實(shí)際卻增加了1次。這種操作時(shí)間問題可能發(fā)生在ns級別,但是以當(dāng)今處理器動輒幾GHZ的速度來說,發(fā)生這種情況概率還是很大的。

2.驗(yàn)證試驗(yàn)

下面我們就做實(shí)驗(yàn)來實(shí)際看看這種情況。

看下程序:

1. #include

2. #include

3. #include

4. #include

5.

6. #define NUM 40000000

7.

8. pthread_t tid1;

9. pthread_t tid2;

10.

11. unsigned int count1 = 0;

12. unsigned int count2 = 0;

13. unsigned int count = 0;

14.

15. void * thr_fn1(void *arg)

16. {

17. while(count1

18. {

19. count++;

20. count1++;

21. }

22. }

23.

24. void * thr_fn2(void *arg)

25. {

26. while(count2

27. {

28. count++;

29. count2++;

30. }

31. }

32.

33. int main(void)

34. {

35. int err;

36.

37. err = pthread_create(&tid1, NULL, thr_fn1, NULL);

38. if (err != 0)

39. perror("can't create thread1");

40.

41. err = pthread_create(&tid2, NULL, thr_fn2, NULL);

42. if (err != 0)

43. perror("can't create thread2");

44.

45. pthread_join(tid1, NULL);

46. pthread_join(tid2, NULL);

47.

48. printf("count = %u, count1 = %u, count2 = %u\n", count, count1, count2);

49. exit(0);

50. }

程序很簡單,就是創(chuàng)建兩個(gè)線程,然后每個(gè)線程分別對count增加40000000 值,這個(gè)值是我隨便選的,只要大一點(diǎn)就行,但是別超了2^32。而count1和count2分別來記錄兩個(gè)線程對count分別增加了多少次,其實(shí)有NUM控制就好了,不過為了對比,我們加入這兩個(gè)變量。主進(jìn)程創(chuàng)建兩個(gè)線程后我們用pthread_join函數(shù)來等待兩個(gè)線程執(zhí)行完畢,并打印三個(gè)值比較得出結(jié)果。

首先在PC機(jī)上看下結(jié)果,CPU是雙核2.6GHZ的,運(yùn)行環(huán)境是ubuntu,順便用time命令查看下執(zhí)行時(shí)間:

從上圖可以看出,兩個(gè)線程對count進(jìn)行總共80000000次累加大概需要2ms多一點(diǎn),測了6次有2次是有問題的,即count != count1 + count2,概率還是比較大的。

然后我把相同的代碼重新編譯拿到AM335x(TI A8單核600MHZ)運(yùn)行,結(jié)果如下

這個(gè)時(shí)間程序耗時(shí)就明顯長了,需要大概4s,本來我以為單核處理器出錯(cuò)概率會小,沒想到運(yùn)行5次結(jié)果居然全是錯(cuò)的。具體為什么會這樣沒去深究,猜想應(yīng)該和SMP機(jī)制及操作系統(tǒng)線程調(diào)度有關(guān)。這個(gè)結(jié)果更證明了線程同步的重要性,尤其是在嵌入式系統(tǒng)中。

3.同步問題解決方案

既然問題都明白了,接下來當(dāng)然是解決方案了,解決這種同步問題經(jīng)典的方案就是鎖了,相信大部分人平時(shí)都用過。以linux線程庫提供的接口,代碼改為下面形式。

1. #define NUM 40000000

2. pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

3.

4. pthread_t tid1;

5. pthread_t tid2;

6.

7. unsigned int count1 = 0;

8. unsigned int count2 = 0;

9. unsigned int count = 0;

10.

11. void * thr_fn1(void *arg)

12. {

13. while(count1

14. {

15. pthread_mutex_lock(&lock);

16. count++;

17. pthread_mutex_unlock(&lock);

18.

19. count1++;

20. }

21. }

22.

23. void * thr_fn2(void *arg)

24. {

25. while(count2

26. {

27. pthread_mutex_lock(&lock);

28. count++;

29. pthread_mutex_unlock(&lock);

30.

31. count2++;

32. }

33. }

只列出了部分代碼,其它的都一樣,其實(shí)思想很簡單,就是在并發(fā)訪問同一個(gè)變量時(shí)候,給這個(gè)共享變量加鎖,保證寫操作的原子性即可。那么為什么count1和count2不用加鎖呢,因?yàn)閮蓚(gè)變量本身就只在兩個(gè)線程中分別操作,所以沒必要加鎖。

后來看下結(jié)果,問題本身已經(jīng)解決了,但是這次重點(diǎn)不在結(jié)果上,而在程序執(zhí)行時(shí)間上。這是在PC上結(jié)果:

這是在ARM上的結(jié)果:

加了這個(gè)操作后,PC上同一程序運(yùn)行時(shí)間多了10倍,板子上多了6倍。所以加鎖操作在保證了并發(fā)訪問正確性同時(shí),大大增加了程序運(yùn)行時(shí)間。所以我們在多進(jìn)程共享資源并發(fā)訪問程序設(shè)計(jì)時(shí)候,需要綜合考慮程序的正確性和效率。

上一篇:如何破解嵌入式產(chǎn)品的telnet密碼

下一篇:Kotlin語法

熱點(diǎn)文章推薦
華清學(xué)員就業(yè)榜單
高薪學(xué)員經(jīng)驗(yàn)分享
熱點(diǎn)新聞推薦
前臺專線:010-82525158 企業(yè)培訓(xùn)洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠(yuǎn)見科技集團(tuán)有限公司 版權(quán)所有 ,京ICP備16055225號-5,京公海網(wǎng)安備11010802025203號

回到頂部