我們提到過使用局部變量、全局變量時,必須注意處理好并發(fā)訪問。
舉個例子:有A、B、C三個線程在并發(fā)執(zhí)行。A線程修改了變量V的值,期望線程C能夠讀取到最新的值。B線程卻在C線程讀取變量V的值之前修改了V的值。這種情況我們說變量V被污染了、數(shù)據(jù)臟了。 要處理好變量的并發(fā)訪問、多線程對變量的訪問,我們需要使用同步機(jī)制。
在多線程軟件設(shè)計中,不僅僅對變量的訪問,對任何競爭性資源的使用/訪問都必須使用合理的同步機(jī)制進(jìn)行管理。比如,有兩個線程都需要使用某個模擬輸出通道,但是模擬輸出通道只有1個、同一時刻只能由1個線程使用,這種情況下我們把這個模擬輸出通道稱作競爭性資源。
如果不對這個模擬輸出通道的訪問進(jìn)行合理的管理,可能導(dǎo)致輸出錯誤的模擬量、線程死鎖、軟件假死等問題。
LabVIEW可用的同步機(jī)制
在Programming->Synchronization分類下,我們可以看到LabVIEW里可用的同步機(jī)制。
名稱 | 作用 | 相關(guān)VI |
通知器操作 Notifier Operations |
掛起某個線程直到收到某個通知 | Wait on Notification、Send Notification等 |
隊(duì)列操作 QueueOperations |
使用隊(duì)列在線程內(nèi)或線程間傳遞數(shù)據(jù) | Enqueue Element、DequeueElement等 |
信號量 Semphore |
通過信號量限制對競爭性資源的訪問 | Acquire Semphore、Release Semphore等 |
集合點(diǎn) Rendezvous |
通過集合點(diǎn)同步多個線程。每個到達(dá)集合點(diǎn)的任務(wù)將等待,直到集合點(diǎn)處等待的任務(wù)達(dá)到指定的數(shù)量后,所有任務(wù)才繼續(xù)執(zhí)行。 | Wait at Rendezvous、Resize Rendezvous等 |
事件發(fā)生 Occurrence |
通過事件發(fā)生控制和同步線程內(nèi)或線程間的活動。 | Generate Occurrence、Wait on Occurrence等 |
首次調(diào)用 First Call? |
判斷某段代碼或某個子VI是否首次執(zhí)行 | / |
同步數(shù)據(jù)流 Synchronize Data Flow |
同步數(shù)據(jù)流,可使用多個線程的數(shù)據(jù)傳送在該VI處得到同步,以確保數(shù)據(jù)傳送順序。 | / |
同步機(jī)制的應(yīng)用
下面我們用具體的例子來詳細(xì)講解一下不同的同步機(jī)制。
1)Notifer Operations
上面這個示例,Loop1和Loop2是兩個并行的線程。這是實(shí)現(xiàn)多線程的最基本的方法。Loop1負(fù)責(zé)產(chǎn)生數(shù)據(jù)和停止這兩個線程的運(yùn)行;Loop2負(fù)責(zé)讀取Loop1產(chǎn)生的數(shù)據(jù),并在需要的時候及時終止線程(退出循環(huán))。它是怎么實(shí)現(xiàn)的呢?Loop2等待數(shù)據(jù)通知器發(fā)出通知、等待終止通知器發(fā)出通知,收到通知后把數(shù)據(jù)讀出來或者退出循環(huán)。Loop1則是把數(shù)據(jù)或者退出控件值通過發(fā)送通知傳遞給Loop2。
第一步:Obtain Notifer,獲取通知器,如果不存在則創(chuàng)建。創(chuàng)建時按照初始值進(jìn)行初始化。
第二步:Send Notification,發(fā)送通知。把數(shù)據(jù)或者控件值通過發(fā)送通知發(fā)送給等待對應(yīng)通知器的線程。
第三步:Wait on Notification,等待通知。Loop2里調(diào)用Wait on Notification掛起線程,直到收到Loop1發(fā)出的通知后繼續(xù)執(zhí)行。
第四步:Release Notifer,釋放通知器。釋放資源,避免內(nèi)存泄露。 這個示例里L(fēng)oop1加了100ms的等待,可以確保通過Send Notification發(fā)送出去的數(shù)據(jù)可以被Loop2獲取到。
如果沒有這個等待100ms,Loop1發(fā)送的數(shù)據(jù)是可能丟失的,通知器不會緩沖已經(jīng)發(fā)送的消息,新的消息會覆蓋舊的消息。如果需要緩沖消息(連帶數(shù)據(jù)),可以使用隊(duì)列。
關(guān)于通知器,我們再看一個VI:Wait on Notification from Multiple,它方便我們等待多個通知,實(shí)現(xiàn)多對一的同步。
2)Queue Operations
下面這個代碼,實(shí)現(xiàn)的功能和上面Notifier Operations里的例子是一樣的。不同的是這里用的是隊(duì)列(Queue)。隊(duì)列的特點(diǎn)是先進(jìn)先出(FIFO)、緩存數(shù)據(jù)。
前面提到過,如果Loop1沒有100ms等待,使用Notifer Operations是可能會丟失數(shù)據(jù)的,但是隊(duì)列這里是不會的。哪怕我們?nèi)コ齃oop1里的100ms等待、在Loop2里加上100ms等待,讓數(shù)據(jù)產(chǎn)生的速度大于數(shù)據(jù)被讀取的速度,也是不會導(dǎo)致數(shù)據(jù)丟失的,來不及被讀取的數(shù)據(jù)都會被存儲在隊(duì)列里。
隊(duì)列不能實(shí)現(xiàn)類似Wait on Notification from Multiple的功能。
3)Semaphore
Semaphore,信號量,是一個常見且重要的概念??梢院唵卫斫鉃轭愃萍t綠燈(信號燈)的功能。四個方向的車都要過十字路口,十字路口又不能同時過的,它是一個競爭性資源,不同方向的車(線程)對它的使用存在競爭。實(shí)際生活中是怎么辦的呢?誰獲得了綠燈(信號量)誰就可以通過。 多個線程訪問競爭性資源前,先嘗試獲取信號量,能夠獲得信號量的線程有權(quán)使用競爭性資源,使用完競爭性資源后釋放信號量(單方向綠燈不能一直亮著?。?/p>
此外,對關(guān)鍵代碼段(Critical Section)也需要使用信號量進(jìn)行保護(hù)。關(guān)鍵代碼段是指涉及變量或競爭性資源訪問的代碼,采用信號量進(jìn)行管理,以避免多個線程同時修改變量或試圖同時訪問競爭性資源。
4)Rendezvous
Rendezvous,集合點(diǎn),比較好理解,大家都到集合點(diǎn)后再出發(fā)。
例如下面這個代碼:
第一步,創(chuàng)建集合點(diǎn)。集合點(diǎn)大小為2,表示需要等待兩個任務(wù)到達(dá)集合點(diǎn)代碼才能往下執(zhí)行。
第二步、第三步,在集合點(diǎn)等待,Wait at Rendezvous。當(dāng)Loop1和Loop2的數(shù)據(jù)流都到達(dá)集合點(diǎn)后,Loop1和Loop2才能夠往下繼續(xù)執(zhí)行。
第四步,銷毀集合點(diǎn),釋放內(nèi)存。
5)Occurrences
事件發(fā)生(Occurrences),用于在不同代碼位置或不同線程之間同步活動。事件發(fā)生不需要輪詢。 例如以下代碼: 第一步,產(chǎn)生一個事件發(fā)生(Occurrence)。 第二步,Loop2等待第一步產(chǎn)生的Occurrence。這個時候Loop2線程被掛起,只有等待的事件發(fā)生(Occurrence)被Set后這個線程才會繼續(xù)執(zhí)行。 第三步,Loop1在完成其它可能的工作后,Set第一步中產(chǎn)生的事件發(fā)生(Occurrence),以使得所有在等待該Occurrence的線程可以繼續(xù)運(yùn)行。
6)First Call?、Synchronize Data Flow
First Call?檢查某段代碼或者某個子VI是否是第一次運(yùn)行。 Synchronize Data Flow用于同步數(shù)據(jù)訪問,它有四個輸入端,并有四個輸出端與輸入端一一對應(yīng)。只有四個輸入端的數(shù)據(jù)都達(dá)到該VI節(jié)點(diǎn)了,代碼才會從該節(jié)點(diǎn)繼續(xù)往下執(zhí)行。 例如下面代碼,當(dāng)First Call?檢查到該VI是第一次運(yùn)行時,先等待四個模擬信號數(shù)據(jù)(可以是實(shí)際項(xiàng)目中的文件讀取、數(shù)據(jù)采集、系統(tǒng)初始化等工作)都到齊后,再往下執(zhí)行代碼。
所以下面這個測試代碼(ONCE就是上面的VI)里,只會有一個Graph控件會有波形數(shù)據(jù)顯示。另一個Graph控件的ONCE子VI被判斷為非首次執(zhí)行,沒有波形數(shù)據(jù)產(chǎn)生。
使用好這些同步機(jī)制可以讓我們設(shè)計出可靠的應(yīng)用軟件。涉及代碼內(nèi)并發(fā)訪問、多線程、競爭性資源使用的,必須采用一定的同步機(jī)制,否則軟件一定會有出錯的時候——可能暫時沒發(fā)現(xiàn),但是隱患一直在。
審核編輯:劉清
-
LabVIEW
+關(guān)注
關(guān)注
2009文章
3679瀏覽量
342169 -
緩沖器
+關(guān)注
關(guān)注
6文章
2168瀏覽量
48190 -
模擬器
+關(guān)注
關(guān)注
2文章
970瀏覽量
45163 -
Graph
+關(guān)注
關(guān)注
0文章
36瀏覽量
9600 -
FIFO存儲
+關(guān)注
關(guān)注
0文章
103瀏覽量
6259
原文標(biāo)題:LabVIEW多線程同步機(jī)制
文章出處:【微信號:傳感測控物聯(lián)網(wǎng),微信公眾號:傳感測控物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
LabView的多線程語言
Linux內(nèi)核同步機(jī)制
多線程同步機(jī)制在應(yīng)用程序與驅(qū)動程序通信中的應(yīng)用
Win32多線程同步技術(shù)淺析

你了解Linux內(nèi)核的同步機(jī)制?
linux多線程機(jī)制-線程同步
Linux下的多線程編程
Linux內(nèi)核的同步機(jī)制

Linux中多線程編程的知識點(diǎn)

如何使用pthread_barrier_xxx系列函數(shù)來實(shí)現(xiàn)多線程之間的同步?

評論