【问题标题】:pthread mutex two threads interchangebly locks/unlocks is it valid approach?pthread mutex 两个线程可互换锁定/解锁是有效的方法吗?
【发布时间】:2012-02-08 14:15:51
【问题描述】:

我读到互斥锁应该由锁定它的同一线程解锁。让我们考虑以下场景。

我有一个互斥变量 myMuteT1T2 是两个线程。

  1. T1 锁定myMute

  2. T2 解锁myMute

  3. T2 锁定myMute

  4. T1 解锁myMute

这种从不同线程有序锁定/解锁的方法是否有效?

【问题讨论】:

  • 不,这违背了拥有 Mutex 的全部目的,即保护一段代码不被另一段代码中断。当您阅读时,它只能通过锁定它的代码来解锁。听起来您有不同的问题 - 也许您应该发布实际问题并寻求正确的解决方案?
  • “应该”是轻描淡写的。互斥锁只能由当前持有它的线程解锁。任何其他线程解锁它的尝试都会导致潜在的非常危险的未定义行为。
  • “一种有效的方法”是什么?你真正想做的是什么?

标签: c linux pthreads


【解决方案1】:

不,这是不正确的。来自pthread_mutex_lock 手册页:

如果线程尝试解锁它尚未锁定的互斥锁或解锁的互斥锁,则会导致未定义的行为。

正确排序示例:

  • T1 锁定 myMutex
  • T2 锁定 myMutex(阻塞等待 T1 解锁互斥锁)
  • T1 解锁 myMutex(T2 现在锁定 mutex)
  • T2 解锁 myMutex

编辑:

使用pthread_cond_wait() 的小例子,为了简洁省略了错误检查:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

volatile int value = 0;
pthread_mutex_t mymutex;
pthread_t thread_one;
pthread_t thread_two;
pthread_cond_t cond;

void* main_one(void* ignored)
{
    while (value < 10)
    {
        pthread_mutex_lock(&mymutex);
        pthread_cond_wait(&cond, &mymutex);
        fprintf(stderr, "T1: value=%d\n", value);
        pthread_mutex_unlock(&mymutex);
    }
    return (void*)0;
}

void* main_two(void* ignored)
{
    int i;

    for (i = 0; i < 10; i++)
    {
        pthread_mutex_lock(&mymutex);
        value++;
        fprintf(stderr, "T2: value=%d\n", value);
        pthread_cond_broadcast(&cond);
        fprintf(stderr, "Broadcasted but T1 cannot continue for 1 second\n");
        sleep(1);
        pthread_mutex_unlock(&mymutex);
        pthread_yield();
    }

    return (void*)0;
}

void start_thread(void* (*a_entry_point)(void*),
                  pthread_t* a_handle)
{
    pthread_attr_t thread_attributes;

    pthread_attr_init(&thread_attributes);
    pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
    pthread_create(a_handle, &thread_attributes, a_entry_point, 0);
}

int main()
{
    pthread_mutexattr_t attr;
    pthread_t thread_one_handle;
    pthread_t thread_two_handle;

    /* Init mutex. */
    pthread_mutexattr_init(&attr);
    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
    pthread_mutex_init(&mymutex, &attr);

    /* Init condition. */
    pthread_cond_init(&cond, 0);

    /* Start threads. */
    start_thread(main_one, &thread_one_handle);
    start_thread(main_two, &thread_two_handle);

    /* Wait for threads. */
    pthread_join(thread_one_handle, 0);
    pthread_join(thread_two_handle, 0);

    /* Clean up. */
    pthread_cond_destroy(&cond);
    pthread_mutex_destroy(&mymutex);

    return 0;
}

使用gcc -Wall -Werror -D_GNU_SOURCE main.c -o main -pthread编译。

【讨论】:

  • 1) 好吧,我以 pthread_cond_wait 为例。它解锁关联的互斥体,并等待,一旦收到信号,然后锁定。 2)。互斥体可用于设置标志,并发出条件变量信号。 3)。我阅读了 Mark、Jeffrey 和 alex 的 Advanced linux Programming,其中 4.4 同步和关键会话章节,提供了相同的代码。相同的互斥变量用于设置条件标志,并且相同的互斥与等待条件变量相关联。我希望我正确地提出了我的问题。 :)
  • pthread_cond_wait 必须在互斥锁锁定的情况下调用,或者像以前一样,导致未定义的行为结果。
  • 是的,没错,但我指出的是 pthread_cond_wait 会自动解锁互斥锁,然后在等待结束后锁定。在等待更改标志的对象之间可以使用相同的互斥锁吗?,这就是我在问题中提到的场景。 :)。
  • 其他线程可以使用该互斥体,在这种情况下pthread_cond_wait 将无法返回。请参阅 Condition Variables 以获取对此的描述。
  • 整点是pthread_cond_wait直到它可以再次获得互斥体才返回。
猜你喜欢
  • 2012-10-24
  • 2011-07-24
  • 2011-05-20
  • 2013-02-02
  • 2015-02-16
  • 2013-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多