【问题标题】:Sharing common variable between 2 functions in multithreaded environment在多线程环境中的 2 个函数之间共享公共变量
【发布时间】:2020-01-21 08:46:41
【问题描述】:

我正在编写一个多线程用例,其中循环在entry() 函数中连续运行,并在调用exit_loop() 时结束。在下面的例子中,entry() 被两个线程调用,当exit_loop() 被调用时两个线程的执行都结束了。

现在我想通过在第一次调用exit_loop() 时仅退出一个线程来稍微改变这一点,即从thread[2] 调用的entry() 仍然存在,当再次调用exit_loop() 时可以终止它。为了使这两个线程独立,我可以将static int loop 移动到本地范围。但我对在entry()exit_loop() 之间传达loop 状态的方式感到震惊。

希望在两个函数之间共享一个公共变量,该变量不得影响和干扰多线程用例。

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

static int loop = 1;
void* entry()
{
    int count = 0;
    while(loop)
    {
        count ++;
        printf("\n Count %d, loop %d",count, loop);
    }
}

void exit_loop()
{
    printf("\n Calling exit loop: %d", loop);
    loop = 0;
    printf("\n loop is null %d", loop);
}

void main()
{   
    sem_t* loop1;
    sem_t* loop2;
    pthread_t threadID[5];
    loop1 = sem_open("sem1", O_CREAT | O_EXCL, 0644, 0);
    if (loop1 != SEM_FAILED)
    {   
        printf("\n Created sem 1");
        pthread_create(&threadID[1], NULL, &entry, NULL);// creating thread 1

    printf("Created thread \n ");
}
else
{
    printf("\n Failed to create Semaphore");
}
sem_close(loop1);

loop2 = sem_open("sem2", O_CREAT | O_EXCL, 0644, 0);
if (loop2 != SEM_FAILED)
{   
    printf("\n Created sem 2");
    pthread_create(&threadID[2], NULL, &entry, NULL);//creating thread 2

    printf("Created thread \n ");
}
else
{
    printf("\n Failed to create Semaphore");
}
sem_close(loop2);

printf("Creating exit thread \n");
exit_loop();// exit of both thread

pthread_join(threadID[1],NULL);
pthread_join(threadID[2],NULL);
}

【问题讨论】:

  • 一种方法是为每个线程设置一个单独的变量。例如int loop[2];。然后调用exit_thread(0)exit_thread(1) 设置所需的loop 条目。最后,正确声明条目:它应该是 void *entry(void *arg) 中指定的 pthread_create man page。这样,您可以使用不同的 arg 值创建每个线程,以告诉它要检查哪个 loop 变量。
  • 你为什么使用信号量?您想要实现的功能只需稍作修改即可完成,您需要在exit_loop() 中有一个可以存储线程ID 的参数,然后使用您要终止的线程ID 调用exit_loop()。您还需要使用提供的线程 ID 调用 pthread_cancel()。请参考 pthread_cancel 手册页。

标签: c linux multithreading pthreads


【解决方案1】:

如果你有两个线程需要独立停止,你需要两个loop变量。

在每种情况下,您都需要一个 mutex 来保护对共享 loop 变量的访问,以防止未定义的行为,因为该变量是从两个线程访问的(一个读取它,一个写入它)。

在它保护的变量旁边声明你的互斥锁:

struct protected_loop_var{
  pthread_mutex_t mutex;
  int value;
};

struct protected_loop_var loop1={PTHREAD_MUTEX_INITIALIZER,1};
struct protected_loop_var loop2={PTHREAD_MUTEX_INITIALIZER,1};

然后,在访问每个loop 变量之前,锁定互斥锁,然后解锁互斥锁。编写单独的函数来访问循环来封装它可能是最简单的。

static int read_loop(struct protected_loop_var* loop){
    pthread_mutex_lock(&loop->mutex);
    int value=loop->value;
    pthread_mutex_unlock(&loop->mutex);
    return value;
}

static void write_loop(struct protected_loop_var* loop,int newval){
    pthread_mutex_lock(&loop->mutex);
    loop->value=newval;
    pthread_mutex_unlock(&loop->mutex);
}

然后你的whileentry 可以说while(read_loop(&amp;loopvar)),在exit_loop 你可以写write_loop(&amp;loopvar,0) 而不是loop=0 其中loopvarloop1loop2 视情况而定。

如果您需要在每个线程上运行相同的代码,那么您可以通过 void* 参数将循环变量的地址传递给该线程。

其他模式可能适用于这种特定情况,但互斥锁是用于保护对共享变量的多线程访问的通用工具。

【讨论】:

  • 感谢您的回答,但我相信这不会解决我的问题。即使这样,所有线程都可以访问公共变量loop。因此,当第一次调用 exit_loop() 时,通过更新 write_loop() 中的 loop。两个活动线程都将其读取为假,问题仍然存在
  • 更新答案以涵盖多个循环变量
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
相关资源
最近更新 更多