简体   繁体   English

线程同步

[英]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. 我将其设置为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. 当我使用锁在另一个线程中读取变量值,对互斥锁进行解锁并读取该值时,我得到的旧值为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. 我在setter函数printf语句中获得了正确的打印输出,它将设置的值设置为传入的id并设置为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. 当我尝试在阅读它们的位置打印它时,两者都仍显示0,这是初始化它们时设置的值。

尝试将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. 您需要将它们设置为extern而不是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. 因此,如果您第一次在侦听器中读取nav_newMovement仍为0,就不会感到惊讶。 nav_newMovement ,请nav_newMovement一些解释,以期望系统如何工作可能会有所帮助。

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 线程#1将信号量#1初始化为锁定,并将信号量#2初始化为未锁定
  2. Thread #1 launches Thread #2, which then locks semaphore #2 and continues on 线程1启动线程2,然后锁定信号2并继续
  3. Meanwhile Thread #1 tries to lock the already locked semaphore #1, so it sits blocked while Thread #2 works 同时,线程#1尝试锁定已经锁定的信号灯#1,因此在线程#2工作时它处于阻塞状态
  4. Thread #2 is finished and unlocks semaphore #1 ... Thread #1 now continues on 线程#2完成并解锁信号灯#1 ...线程#1现在继续
  5. Thread #2 tries to lock semaphore #2, but it's locked, so it must wait for Thread #1 to finish working 线程2试图锁定信号量2,但是它已被锁定,因此它必须等待线程1结束工作。
  6. Thread #1 finishes working and unlocks semaphore #2 ... Thread #2 now continues 线程#1完成工作并解锁信号灯#2 ...线程#2现在继续
  7. Thread #1 tries to lock semaphore #1, but it's locked, so it must wait for Thread #2 to finish working 线程1试图锁定信号量1,但是它已被锁定,因此它必须等待线程2才能完成工作
  8. Keep repeating until you reach some finishing condition ... 不断重复直到达到某种整理状态...

So basically Thread #1 unlocks Thread #2, and vice versa. 因此,基本上,线程1解锁线程2,反之亦然。 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. 线程#1不会解锁自身,然后锁定线程#2,或其他一些变化,其中单个线程必须同时锁定和解锁自己和另一个线程的信号量。 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. 您将可以确定地说一个线程不能继续经过某个点,直到另一个线程到达某个点为止...因此,您的同步点是使用信号量的固有特性创建的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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