首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当使用4个线程在程序上调用pthread_cond_signal时,同一个线程将获得互斥对象。

当使用4个线程在程序上调用pthread_cond_signal时,同一个线程将获得互斥对象。
EN

Stack Overflow用户
提问于 2018-10-04 23:58:16
回答 2查看 103关注 0票数 2
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_t node[4];
pthread_mutex_t token;
pthread_cond_t cond;
int id=0;

void *func(int n)
   {
        int count = 0;
        while (count < 10){
                 pthread_mutex_lock(&token);
                while (id != n){
                        printf("Whoops not my turn, id=%d\n",n);
                        pthread_cond_wait(&cond, &token);}
                //if (id == n){
                        count += 1;
                        printf ("My turn! id= %d\n",n);
                        printf("count %d\n", count);
                        if (id == 3){
                                id = 0;}
                        else{
                                id += 1;}
                        //}else{
                        //      printf("Not my turn! id=%d\n",n);}
                        //      pthread_mutex_unlock(&token);
                        //      sleep(2);}
                        pthread_mutex_unlock(&token);
                        pthread_cond_signal(&cond);}
                        printf ("ID=%d has finished\n",n);

        return(NULL);
   }

int main()
   {
   int i;
   pthread_mutex_init(&token,NULL);
        pthread_cond_init(&cond,NULL);
   for(i=0;i<4;i++)
      pthread_create(&node[i],NULL,(void *)func,(void *)i);

   for(i=0;i<4;i++)
      pthread_join(node[i],NULL);

   pthread_mutex_destroy(&token);

   return 0;
   }

这是我的代码,它是一个使用线程的C程序。我不认为它的目的需要知道在这里,但我会给出一个例子,我有问题。

假设使用id 1的线程(在func中由n定义)获取互斥体,并返回"My!id=1“。当调用mutex_unlock和cond_signal时,获取互斥对象的下一个线程实际上将再次为id 1的线程,它将打印“不要轮到我,id=1”。只有这样,使用id 2的线程才会得到互斥体,并打印"My!id=2",但是当id =2的线程在那之后得到互斥的时候。这是我的程序输出:

代码语言:javascript
复制
Whoops not my turn, id=1
Whoops not my turn, id=2
Whoops not my turn, id=3
My turn! id= 0
count 1
Whoops not my turn, id=0
My turn! id= 1
count 1
Whoops not my turn, id=1
My turn! id= 2
count 1
Whoops not my turn, id=2
My turn! id= 3
count 1
Whoops not my turn, id=3
My turn! id= 0
count 2
Whoops not my turn, id=0
My turn! id= 1
count 2
Whoops not my turn, id=1
My turn! id= 2
count 2
Whoops not my turn, id=2
My turn! id= 3
count 2
Whoops not my turn, id=3
My turn! id= 0
count 3
Whoops not my turn, id=0
My turn! id= 1
count 3
Whoops not my turn, id=1
My turn! id= 2
count 3
Whoops not my turn, id=2
My turn! id= 3
count 3
Whoops not my turn, id=3
My turn! id= 0
count 4
Whoops not my turn, id=0
My turn! id= 1
count 4
Whoops not my turn, id=1
My turn! id= 2
count 4
Whoops not my turn, id=2
My turn! id= 3
count 4
Whoops not my turn, id=3
My turn! id= 0
count 5
Whoops not my turn, id=0
My turn! id= 1
count 5
Whoops not my turn, id=1
My turn! id= 2
count 5
Whoops not my turn, id=2
My turn! id= 3
count 5
Whoops not my turn, id=3
My turn! id= 0
count 6
Whoops not my turn, id=0
My turn! id= 1
count 6
Whoops not my turn, id=1
My turn! id= 2
count 6
Whoops not my turn, id=2
My turn! id= 3
count 6
Whoops not my turn, id=3
My turn! id= 0
count 7
Whoops not my turn, id=0
My turn! id= 1
count 7
Whoops not my turn, id=1
My turn! id= 2
count 7
Whoops not my turn, id=2
My turn! id= 3
count 7
Whoops not my turn, id=3
My turn! id= 0
count 8
Whoops not my turn, id=0
My turn! id= 1
count 8
Whoops not my turn, id=1
My turn! id= 2
count 8
Whoops not my turn, id=2
My turn! id= 3
count 8
Whoops not my turn, id=3
My turn! id= 0
count 9
Whoops not my turn, id=0
My turn! id= 1
count 9
Whoops not my turn, id=1
My turn! id= 2
count 9
Whoops not my turn, id=2
My turn! id= 3
count 9
Whoops not my turn, id=3
My turn! id= 0
count 10
ID=0 has finished
My turn! id= 1
count 10
ID=1 has finished
My turn! id= 2
count 10
ID=2 has finished
My turn! id= 3
count 10
ID=3 has finished

如您所见,每次成功后,线程打印“我的回合!”之后,它将得到互斥,并造成“呼呼而不是我的回合!”。我不明白为什么在我调用pthread_cond_signal时会发生这种情况,它应该会指示另一个线程在当前线程重新获得互斥对象之前醒来。请帮助我找到这个解决方案,因为我认为有重要的东西,我错过了。如果我没有解释,请随时向我索取更多的信息。非常感谢您的时间!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-05 07:40:39

@rcgldr已经给出了一个非常好的解释所涉及的时间。如果您想增加给另一个线程一个机会的可能性,请尝试添加一个对yield的调用,这将给调度程序选择不同线程的机会,尽管这也不是一个保证。

票数 0
EN

Stack Overflow用户

发布于 2018-10-05 00:18:05

在Linux (可能还有posix系统)的情况下,无法保证互斥锁请求得到服务的顺序。当互斥锁被解锁时,操作系统不会强制进行上下文切换,因此当前运行的线程继续其循环并再次锁定互斥锁。我不知道您是否可以通过p线程接口更改线程优先级,但如果可以的话,您可以只增加线程"(n)%4“的优先级,而当线程"(n)%4”运行时,它会将其优先级设置为正常的,并将线程"(n+1)%4“设置为更高的优先级。

在Windows使用其本机互斥体的情况下,显然锁请求的顺序在队列或等效的队列中被跟踪,因此当当前运行的线程循环回锁请求时,Windows将切换到互斥锁请求队列中的第一个线程。我不知道这是否有记录,但我已经证实它是这样工作的。我不知道Windows中的线程互斥体是否会以这种方式工作。

一个可能的替代方案是每个线程一个互斥,但我不知道这是否会导致任何问题,取决于操作系统。每个线程使用一个信号量应该有效。

附带注意,如果使用条件变量,您可以得到一个虚假的唤醒,并将需要处理这种情况。

wakeup

但是,如果使用本机Windows同步类型,如互斥、信号量、.,则不会发生虚假的唤醒。

对于一些操作系统,如Linux,这些问题已经足够了,一些高端的多线程应用程序安装了内核级驱动程序,以实现内核时间自旋锁以避免这些问题。

https://en.wikipedia.org/wiki/Spinlock

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52656580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档