繁体   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