简体   繁体   中英

Thread synchronization

I have one thread that locks a mutex, writes a value to a variable, unlocks the mutex. I do a print out here and the value has been changed. I set it to 1.

When I read the variables value in another thread using lock, unlock on the mutex and read the value, I get the old value of 0.

Why is this happening. I lock and unlock the same mutex correctly.

How do I sync threads?

EDIT:

I declare the mutexes and variables here

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;

I set the variables here

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");
}

and read them here

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)

I get the correct print outs in the setter functions printf statements, it set the values to id that is passed in and to 1.

When I try print it where I read them, both are still showing 0, which is what they were set to when I initialized them.

尝试将volatile说明符添加到nav_movementIdnav_newMovement变量。

These declarations:

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

create entirely new and different variables - that's why you don't see the modifications to the global variable. Make the declaration like so so the function that's updating the variables is acting on the global instances:

extern int nav_movementId;
extern int nav_newMovement;

Similarly, the mutexes need to be the same instances - they need to be globals or you need to arrange to get their addresses shared between the modules.

In one module:

pthread_mutex_t movementIdMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t newMovementMutex = PTHREAD_MUTEX_INITIALIZER;

In a header (or the other module):

extern pthread_mutex_t movementIdMutex;
extern pthread_mutex_t newMovementMutex;

Are those static mutexes and variables in the same source file as the code below, or are they in a header? If they are in a header and those two functions are in separate files, then each one has it's own copy of the mutex and variable. You need to make them extern instead of static.

Another thing: The "listener" function is not actually waiting for the variables to be set by the other function - the mutex is only ensuring that they are not being actively written to. So I wouldn't be suprised if the first time you read nav_newMovement in the listener that it is still 0. A little more explanation of how you expect the system to works might help here.

Thread execution order is indeterminant, meaning just because you've launched a thread doesn't mean that the execution order of the threads will be in the order you've launched them. In order to sync threads then, you have to create "barriers", that is a point in the code where one thread cannot continue until another thread has reached a specific point. This is typically done with semaphores, although you can do it with mutexes and condition variables.

The concept is that if you had two threads, and two semaphores, you can cause one thread to block while the other thread is running. Then when the first thread is done running, it unblocks the second thread, and the second thread blocks the first thread. This can keep repeating where one thread blocks while the other thread works and vice versa. So the steps would be:

  1. Thread #1 initializes semaphore #1 as locked, and semaphore #2 as unlocked
  2. Thread #1 launches Thread #2, which then locks semaphore #2 and continues on
  3. Meanwhile Thread #1 tries to lock the already locked semaphore #1, so it sits blocked while Thread #2 works
  4. Thread #2 is finished and unlocks semaphore #1 ... Thread #1 now continues on
  5. Thread #2 tries to lock semaphore #2, but it's locked, so it must wait for Thread #1 to finish working
  6. Thread #1 finishes working and unlocks semaphore #2 ... Thread #2 now continues
  7. Thread #1 tries to lock semaphore #1, but it's locked, so it must wait for Thread #2 to finish working
  8. Keep repeating until you reach some finishing condition ...

So basically Thread #1 unlocks Thread #2, and vice versa. Thread #1 does not unlock itself and then lock Thread #2, or some other variation where a single thread has to both lock and unlock a semaphore for itself and another thread. That way you don't end up with a "cross-over" point where neither thread is locked and their both running free, or worse, a dead-lock condition where both threads are waiting for the other thread to unlock themselves.

By using semaphores, you can effectively create "barriers" in your application that will allow for some level of determinism in the way threads are run, and create threads that are synchronized to each other. You will be able to deterministically say that a thread cannot continue past a certain point until another thread has reached a certain point ... hence your synchronization points are created using the inherent nature of a semaphore.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM