【问题标题】:Thread concurrency in linuxlinux中的线程并发
【发布时间】:2015-06-19 10:39:46
【问题描述】:

我是 SO 的初学者,所以如果问题不清楚,请告诉我。

我正在使用两个线程,例如 A 和 B。我有一个全局变量“p”。 线程 A 正在循环并增加 'p' 的值。同时 B 试图将 'p' 设置为其他值(两者都是两个不同的线程函数)。

如果我使用互斥锁进行同步,并且线程 A 获取互斥锁并在 while 循环中递增“p”,但它不会释放互斥锁。 所以我的问题是,如果线程 A 不释放互斥锁,线程 B 可以访问变量 'p' 吗??

编辑 线程 B 也使用互斥锁来保护对 'p' 的访问。

如果线程 A 使用 pthread_mutex_lock() 锁定并且没有释放它,那么如果同一个线程 (A) 尝试再次访问锁会发生什么(记住线程 A 正在循环中) 例如

   while(1)
        {
            pthread_mutex_lock(&mutex);
            p = 10;

        }

如果互斥锁从不释放,这段代码有什么问题吗?

【问题讨论】:

  • 线程 B 可以访问该变量,如果您没有使用互斥锁保护该访问(这是您没有告诉我们的部分)。
  • 如果B正在使用互斥锁,不,它不能访问p。如果 B 没有使用互斥锁,是的,它可能会改变 p 并且你有问题!添加您的示例代码,我们可以明确回答。
  • 编辑后:线程 B 将永远等待获取互斥锁。
  • pthread_mutex_lock 上的手册是怎么说的?
  • 你对互斥锁的使用是 1。如果你从不解锁它就没什么用了。 2. 如果互斥锁是 PTHREAD_MUTEX_NORMAL 是非常危险的 - pthread_mutex_lock 的文档回答了这个问题 - 你的程序将死锁。

标签: c pthreads mutex


【解决方案1】:

您仍然可以访问线程 B 中的变量,因为互斥锁是一个未连接到变量的单独对象。如果您在访问p 之前从线程B 调用互斥锁,那么线程B 将等待互斥锁被释放。事实上,线程 A 只会执行一次循环体,因为它会等待互斥体被释放,然后才能再次锁定它。

如果您不解锁互斥锁,则任何锁定同一互斥锁的调用都将无限期等待,但该变量将是可写的。

在您的示例中,对变量 p 的访问是所谓的临界区,或互斥锁和互斥释放之间的代码部分。

【讨论】:

    【解决方案2】:

    互斥量没有限制,你需要按照互斥量的使用规则编写程序。

    以下是在共享资源上使用互斥锁的基本步骤:

    • 先获取锁
    • 做作业(A增加,B设定值)
    • 释放锁定,

    如果 A 和 B 都遵守规则,那么 B 不能修改它,而 A 保留锁。

    或者,如果你的线程 B 没有首先获取锁,它可能会修改变量,但这对于并发编程来说是一个错误。

    顺便说一句,你还可以将conditionmutex一起使用,这样你就可以让线程相互等待和通知,而不是一直循环,浪费机器资源。


    关于您更新的问题

    在linux上,在c中,获取互斥锁的方法主要有3种,线程拿不到锁怎么办,就看你用的是什么方法了。

    • int pthread_mutex_lock(pthread_mutex_t * mutex );

    如果它已经被另一个线程锁定,那么它会阻塞直到锁被解锁,

    • int pthread_mutex_trylock(pthread_mutex_t * mutex );

    类似于pthread_mutex_lock(),但不会阻塞,而是返回错误EBUSY,

    • int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex, const struct timespec *restrict abs_timeout);

    类似于pthread_mutex_lock(),但它会在返回错误ETIMEDOUT之前等待超时,

    【讨论】:

    • 您的回答有点令人困惑。我不确定这是真的。这就是互斥锁的用途:每个并发进程/线程的锁定工作释放。
    【解决方案3】:

    静态初始化互斥锁的简单示例

    #include <pthread.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    static int p = 0;
    static pthread_mutex_t locker = PTHREAD_MUTEX_INITIALIZER;
    
    static void *
    threadFunc(void *arg)
    {
      int err;
      err = pthread_mutex_lock(&locker);
      if (err != 0){
        perror("pthread_mutex_lock failed");
        exit(1);
      }
      p++;
      err = pthread_mutex_unlock(&locker);
      if (err != 0){
        perror("pthread_mutex_unlock failed");
        exit(1);
      }
      return NULL;
    }
    
    int
    main(int argc, char *argv[])
    {
      pthread_t A, B;
      pthread_create(&A, NULL, threadFunc, NULL);
      pthread_create(&B, NULL, threadFunc, NULL);
      pthread_join(A, NULL);
      pthread_join(B, NULL);
      printf("p = %d\n", p);
      return 0;
    }
    

    为简洁起见省略了 main 中的错误检查,但应该使用。如果不释放 mutex 程序永远不会结束,线程 B 永远不会得到锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-05-21
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 2018-03-08
      相关资源
      最近更新 更多