【问题标题】:Concurrency in Linux: Alternate access of two threads in critical zoneLinux 中的并发:临界区中两个线程的交替访问
【发布时间】:2016-04-22 17:03:09
【问题描述】:

我是 Linux 中并发和线程概念的新手,我试图解决一个相对简单的问题。我创建了两个线程,它们运行相同的函数,增加一个全局变量。我真正想从我的程序中增加该变量,也就是说,在每个步骤中,增加该变量的线程会在屏幕上打印一条消息,因此预期的输出应该如下所示:

Thread 1 is incrementing variable count... count = 1
Thread 2 is incrementing variable count... count = 2
Thread 1 is incrementing variable count... count = 3
Thread 2 is incrementing variable count... count = 4

等等。

我尝试了一个带有信号量的实现,以确保互斥,但结果类似于:

Thread 2 is incrementing variable count... count = 1
Thread 2 is incrementing variable count... count = 2
Thread 2 is incrementing variable count... count = 3
Thread 2 is incrementing variable count... count = 4
Thread 2 is incrementing variable count... count = 5
Thread 1 is incrementing variable count... count = 6
Thread 1 is incrementing variable count... count = 7
Thread 1 is incrementing variable count... count = 8
Thread 1 is incrementing variable count... count = 9
Thread 1 is incrementing variable count... count = 10

我的代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>

int count = 0;
sem_t mutex;

void function1(void *arg)
{
        int i = 0;
        int *a = (int*) arg;

        while (i < 10)
        {
           sem_wait(&mutex);
           count++;
           i++;
           printf("From the function : %d count is %d\n",*a,count);
           sem_post(&mutex);
        }
}

int main()
{
    pthread_t t1,t2;
    int a = 1;
    int b = 2;
    pthread_create(&t1,NULL,(void *)function1,&a);
    pthread_create(&t2,NULL,(void *)function1,&b);

    sem_init(&mutex,0,1);
    pthread_join(t2,NULL);
    pthread_join(t1,NULL);
    sem_destroy(&mutex);
    return 0;
}

我现在最大的问题是,如何实现线程之间的这种交替?我得到了互斥,但仍然缺少交替。也许我对信号量的使用缺乏深入的了解,但如果有人能向我解释这一点,我将不胜感激。 (我看过几门关于这个主题的课程,即Linux信号量,并发和线程,但那里的信息不够令人满意)

【问题讨论】:

    标签: linux multithreading concurrency semaphore


    【解决方案1】:

    互斥锁不保证任何公平性。这意味着如果线程 1 释放它然后尝试再次获取它,则不能保证它不会 - 它只是保证不能在该块中同时运行两条代码。

    编辑: 删除了以前的 C 样式解决方案,因为它可能不正确。该问题要求提供同步解决方案。

    如果你真的想正确地做到这一点,你会使用一个叫做监视器和守卫(或条件变量)的东西。我对 C 和 pThreads 不太熟悉,所以你需要看看如何使用它,但在 Java 中它看起来像:

      public class IncrementableInteger {
        public int value;
    
        @Override
        public String toString() {
          return String.valueOf(value);
        }
      }
    
      @Test
      public void testThreadAlternating() throws InterruptedException {
        IncrementableInteger i = new IncrementableInteger();
    
        Monitor m = new Monitor();
        Monitor.Guard modIsZeroGuard = new Monitor.Guard(m) {
          @Override public boolean isSatisfied() {
            return i.value % 2 == 0;
          }
        };
    
        Monitor.Guard modIsOneGuard = new Monitor.Guard(m) {
          @Override public boolean isSatisfied() {
            return i.value % 2 == 1;
          }
        };
    
        Thread one = new Thread(() -> {
          while (true) {
            m.enterWhenUninterruptibly(modIsZeroGuard);
            try {
              if (i.value >= 10) return;
              i.value++;
              System.out.println("Thread 1 inc: " + String.valueOf(i));
            } finally {
              m.leave();
            }
          }
        });
    
        Thread two = new Thread(() -> {
          while (true) {
            m.enterWhenUninterruptibly(modIsOneGuard);
            try {
              if (i.value >= 10) return;
              i.value++;
              System.out.println("Thread 2 inc: " + String.valueOf(i));
            } finally {
              m.leave();
            }
          }
        });
    
        one.start();
        two.start();
    
        one.join();
        two.join();
      }
    

    【讨论】:

    • 我已经在我的IDE中编写了代码,它实际上在第一次打印后就阻塞了
    • 所以我认为它实际上并没有阻塞,可能发生的情况是第一个线程只是不断地获取互斥锁。因此,如果您要在 if 语句之外添加一个 print 说“线程 *a 正在运行”,您应该会看到它不断地打印出来。是这样吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2013-06-05
    • 1970-01-01
    • 2012-07-27
    • 2018-09-09
    相关资源
    最近更新 更多