2017-09-20 80 views
2

我有一個在Ubuntu上使用git://github.com/raspberrypi/tools.git工具在RaspberryPi(3)上交叉編譯的項目。我想與condition_variable一起使用線程同步,但wait_for似乎不會釋放提供給它的mutex上的鎖定,如文檔中所述。下面是轉載了樹莓派的問題簡化代碼(有過多的日誌記錄,以更好地可視化的問題):std :: condition_variable ::等待不釋放RaspberryPi上的鎖

int main(int argc, const char* args[]) 
{ 
    std::condition_variable cv; 
    std::mutex m; 
    bool ok = false; 

    std::cout << "locking in main" << std::endl; 
    std::unique_lock<std::mutex> lock(m); 
    std::cout << "locked in main" << std::endl; 

    std::cout << "starting thread" << std::endl; 
    std::thread t([&cv, &m, &ok]() { 
     std::cout << "locking in thread" << std::endl; 
     std::unique_lock<std::mutex> lock(m); 
     std::cout << "locked in thread" << std::endl; 
     ok = true; 

     std::cout << "unlocking in thread" << std::endl; 
     lock.unlock(); 
     std::cout << "signalling cv" << std::endl; 
     cv.notify_one(); 
    }); 

    std::cout << "starting wait" << std::endl; 
    bool success = cv.wait_for(lock, std::chrono::seconds(10), [&ok]{ return ok; }); 
    std::cout << "finished waiting: " << success << std::endl; 

    std::cout << "unlocking in main" << std::endl; 
    lock.unlock(); 
    std::cout << "joining thread" << std::endl; 
    t.join(); 
    std::cout << "thread joined" << std::endl; 

    return 0; 
} 

這是我比較獲得標準G ++ linux版側樹莓控制檯上並排輸出:

RPi version:    linux version: 
locking in main    locking in main 
locked in main    locked in main 
starting thread    starting thread 
starting wait    starting wait 
locking in thread   locking in thread 
finished waiting: 0   locked in thread 
unlocking in main   unlocking in thread 
joining thread    signalling cv 
locked in thread   finished waiting: 1 
unlocking in thread   unlocking in main 
signalling cv    joining thread 
thread joined    thread joined 

這讓我相信代碼很好,並且RaspberryPi交叉編譯或標準庫存在問題。我是否錯過了一些東西,是否有解決這個問題的方法?

編輯: 問題最早是在依賴於升壓和socket.io客戶端一個更大的項目的注意。我將main簡化爲問題中的一個,但沒有刪除其餘的代碼。它被編譯和鏈接如下:

[...] 
arm-linux-gnueabihf-g++ -std=c++1y -I%SRC_DIR%/rapidjson/include -I%SRC_DIR%/boost_1_65_0/install/include -I%SRC_DIR%/socket.io-client-cpp/build/include -O3 -g -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.o" -o "main.o" "../main.cpp" 
[...] 
arm-linux-gnueabihf-g++ -L%SRC_DIR%/boost_1_65_0/install-arm/lib -L%SRC_DIR%/socket.io-client-cpp/build-arm/lib/Release -L%SRC_DIR%/openssl/build-arm/lib -static -pthread -o "main" [...] ./main.o [...] -lsioclient -lboost_system -lssl -lcrypto -ldl 

其中其他目標文件被替換爲[...],socket.io-client需要libssl。但是,如果我只編譯arm-linux-gnueabihf-g++ -pthread -std=c++1y -O3 -g -Wall -o main1 main1.cpp的張貼片段,它在RaspberryPi上也可以正常工作,所以它可能不是交叉編譯工具的問題。其中一個依賴關係是否有可能對發生的事情負責?

+0

你如何編譯它? – VTT

+0

該日誌僅顯示在主線程中超時之前未在線程中獲取鎖的**。你有沒有嘗試用簡單的'wait'替換'wait_for'?在超時之前沒有獲得鎖*,並且根本沒有獲得鎖*是不同的事情。 – Tsyvarev

回答

1

看來,我的鏈接器命令是不正確的,(可能)導致pthread被靜態鏈接,這是由於交叉編譯,並不是RaspberryPi上系統所需的正確版本。按我的問題的編輯,我原來的錯誤(簡體)鏈接命令是這樣的:terminate called after throwing an instance of 'std::system_error' what(): Enable multithreading to use std::thread: Operation not permitted

arm-linux-gnueabihf-g++ -Lsome_dirs -static -pthread -o "main" ./main.o ./some_object_files -lsome_libs 

在單一的main.cpp文件的簡單的情況下,這樣的連接選項,同時創建一個線程報告了一個錯誤。它最初把我扔了,但實際上是一個有價值的線索。

要解決,我不得不修改鏈接命令靜態鏈接我需要靜態鏈接庫,而動態鏈接並行線程,像這樣的問題:

arm-linux-gnueabihf-g++ -o "main" ./main.o ./some_object_fiels -Lsome_dirs -Wl,-Bstatic -lsome_libs -Wl,-Bdynamic -ldl -pthread 
0

試試這個

std::cout << "locking in main" << std::endl; 
std::unique_lock<std::mutex> lock(m); 
std::cout << "locked in main" << std::endl; 

std::cout << "starting thread" << std::endl; 
std::thread t([&cv, &m, &ok]() { 
    std::cout << "locking in thread" << std::endl; 
    std::unique_lock<std::mutex> lock(m); 
    std::cout << "locked in thread" << std::endl; 
    ok = true; 
    std::cout << "unlocking in thread" << std::endl; 
    std::cout << "signalling cv" << std::endl; 
    cv.notify_one(); 
}); 

std::cout << "starting wait" << std::endl; 
while(!ok) 
    cv.wait(lock); 
std::cout << "finished waiting: " << ok << std::endl; 

std::cout << "unlocking in main" << std::endl; 
lock.unlock(); 
std::cout << "joining thread" << std::endl; 
t.join(); 
std::cout << "thread joined" << std::endl; 

Furthemore,我認爲你應該避免線程內解鎖互斥,因爲範圍的結束,unique_lock自動釋放鎖

相關問題