簡體   English   中英

線程同步

[英]Thread synchronization

我有一個鎖定互斥鎖,將值寫入變量,解鎖互斥鎖的線程。 我在這里進行打印,並且值已更改。 我將其設置為1。

當我使用鎖在另一個線程中讀取變量值,對互斥鎖進行解鎖並讀取該值時,我得到的舊值為0。

為什么會這樣呢? 我正確鎖定和解鎖了相同的互斥鎖。

如何同步線程?

編輯:

我在這里聲明互斥鎖和變量

static pthread_mutex_t movementIdMutex = PTHREAD_MUTEX_INITIALIZER;
static int nav_movementId = 0;

static pthread_mutex_t newMovementMutex = PTHREAD_MUTEX_INITIALIZER;
static int nav_newMovement = 0;

我在這里設置變量

void nav_setMovementIdentifier(int id)
{
printf("Received movement id:%d from connectivity\n", id);

int result; /* Use the result for testing */

result = pthread_mutex_lock(&movementIdMutex);
nav_movementId = id;
printf("nav_movementId is %d\n", nav_movementId);
result = pthread_mutex_unlock(&movementIdMutex);

result = pthread_mutex_lock(&newMovementMutex);
nav_newMovement = 1;
printf("nav_newMovement is %d in the setId function\n", nav_newMovement);
result = pthread_mutex_unlock(&newMovementMutex);
printf("\n");
}

並在這里閱讀

void *startConnectivityListener(void *ptr)     {

/* Declare safety variables because segments cant be locked/unlocked 
*  using mutexes if they are checking in statement such as if and while.
*/
int newMoveCheck = 0;
int startIndoorCheck = 0;
int startOutdoorCheck = 0;

int listening = 1;

while(listening == 1)
{
    int result; /* Use for testing */

    /* check if a new movement command waits */
    result = pthread_mutex_lock(&newMovementMutex);
    newMoveCheck = nav_newMovement;
    printf("nav new movement in thread is :%d\n", nav_newMovement);
    printf("newMoveCheck in mutex lock is:%d\n", newMoveCheck);
    result = pthread_mutex_unlock(&newMovementMutex);

    result = pthread_mutex_lock(&movementIdMutex);
    printf("nav_movementId in thread is %d\n", nav_movementId);
    result = pthread_mutex_unlock(&movementIdMutex);

    printf("newMoveCheck is %d\n", newMoveCheck);
    sleep(1);

    if(newMoveCheck == 1)

我在setter函數printf語句中獲得了正確的打印輸出,它將設置的值設置為傳入的id並設置為1。

當我嘗試在閱讀它們的位置打印它時,兩者都仍顯示0,這是初始化它們時設置的值。

嘗試將volatile說明符添加到nav_movementIdnav_newMovement變量。

這些聲明:

static int nav_movementId = 0;
static int nav_newMovement = 0;

創建全新的不同變量-這就是為什么看不到全局變量的修改的原因。 像這樣進行聲明,以便更新變量的函數作用於全局實例:

extern int nav_movementId;
extern int nav_newMovement;

同樣,互斥鎖必須是相同的實例-它們必須是全局實例,或者您需要安排它們在模塊之間共享地址。

在一個模塊中:

pthread_mutex_t movementIdMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t newMovementMutex = PTHREAD_MUTEX_INITIALIZER;

在標題(或其他模塊)中:

extern pthread_mutex_t movementIdMutex;
extern pthread_mutex_t newMovementMutex;

這些靜態互斥鎖和變量是與以下代碼位於同一源文件中還是位於標頭中? 如果它們在標題中,而這兩個函數在單獨的文件中,則每個函數都有其自己的互斥體和變量副本。 您需要將它們設置為extern而不是static.

另一件事:“偵聽器”功能實際上並沒有在等待其他功能設置的變量-互斥體僅確保它們沒有被主動寫入。 因此,如果您第一次在偵聽器中讀取nav_newMovement仍為0,就不會感到驚訝。 nav_newMovement ,請nav_newMovement一些解釋,以期望系統如何工作可能會有所幫助。

線程執行順序是不確定的,這意味着僅僅因為您啟動了一個線程並不意味着線程的執行順序將與您啟動它們的順序相同。 為了同步線程,您必須創建“屏障”,這是代碼中的一個點,其中一個線程無法繼續,直到另一個線程到達特定點為止。 盡管您可以使用互斥量和條件變量來完成此操作,但通常使用信號量來完成。

這個概念是,如果您有兩個線程和兩個信號量,則可能導致一個線程阻塞而另一個線程正在運行。 然后,當第一個線程完成運行時,它解除阻塞第二個線程,而第二個線程阻塞第一個線程。 這樣可以在一個線程阻塞而另一個線程正常工作的地方繼續重復,反之亦然。 因此,步驟將是:

  1. 線程#1將信號量#1初始化為鎖定,並將信號量#2初始化為未鎖定
  2. 線程1啟動線程2,然后鎖定信號2並繼續
  3. 同時,線程#1嘗試鎖定已經鎖定的信號燈#1,因此在線程#2工作時它處於阻塞狀態
  4. 線程#2完成並解鎖信號燈#1 ...線程#1現在繼續
  5. 線程2試圖鎖定信號量2,但是它已被鎖定,因此它必須等待線程1結束工作。
  6. 線程#1完成工作並解鎖信號燈#2 ...線程#2現在繼續
  7. 線程1試圖鎖定信號量1,但是它已被鎖定,因此它必須等待線程2才能完成工作
  8. 不斷重復直到達到某種整理狀態...

因此,基本上,線程1解鎖線程2,反之亦然。 線程#1不會解鎖自身,然后鎖定線程#2,或其他一些變化,其中單個線程必須同時鎖定和解鎖自己和另一個線程的信號量。 這樣一來,您就不會遇到一個“交叉”點,即兩個線程都沒有被鎖定,並且兩個線程都自由運行,或者更糟的是,兩個線程都在等待另一個線程自己解鎖的死鎖狀態。

通過使用信號量,您可以在應用程序中有效地創建“屏障”,從而在線程運行方式上實現一定程度的確定性,並創建彼此同步的線程。 您將可以確定地說一個線程不能繼續經過某個點,直到另一個線程到達某個點為止...因此,您的同步點是使用信號量的固有特性創建的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM