1

I can not think of a logical solution to the problem. There are two streams - the main and child. They must in turn display a message like this:

Parent

Child

Parent

... and so forth 10 times each.

You can only use pthread mutexes and do not use idle cycle. Idle cycle is allowed only during the initialization phase. Who - anyone know of a nice solution?

4

3 回答 3

3

我想我明白了……最大的提示是“在初始化阶段只能进行空闲”。

首先,对互斥锁的限制是您必须在锁定的同一线程中解锁。因此unlock(),线程中的每个线程都必须与 a 配对lock(),并且我们必须拥有相等数量的互斥锁(否则我们会陷入死锁)。

这意味着我们可以防止线程多次打印的唯一方法是确保每个线程始终拥有至少一个互斥体。如果线程 B 在任何时候释放了它所有的互斥体,然后 CPU 切换到线程 A,它就可以无限期地运行。

我们不能用 2 个没有死锁的互斥锁来做到这一点,但我们可以用 3 个来做到这一点。

父线程:

    bool initDone = false;
    lock(m1);
    lock(m2);
    spawnChild();
    while (!initDone)
        sleep();
    while (true) {
        print("Parent");
        unlock(m1);
        lock(m3);
        unlock(m2);
        lock(m1);
        unlock(m3);
        lock(m2);
    }

子线程:

    lock(m3);
    initDone = true;
    while (true) {
        lock(m1);
        unlock(m3);
        lock(m2);
        print("Child");
        unlock(m1);
        lock(m3);
        unlock(m2);
    }

我们从父级拥有锁 1 和 2,子级拥有 3 开始。然后他们轮流释放和获取锁:父级给子级锁 1,子级给父级锁 3,父级给子级锁 2,子级给锁 1父母,父母给孩子锁3,孩子给父母锁2,重复。

一个有趣的问题;我敢打赌,您现在看到了条件变量的吸引力,因为它们使这一点变得微不足道。

于 2013-10-28T18:50:52.477 回答
0

您需要的是 2 个线程(父线程和子线程)允许彼此执行。

这是伪代码,您可以随意使用任何您想要的锁定原语。

//global variables and initializations
parent_lock = UNLOCKED; //This allows your first print to be from parent
child_lock = LOCKED;

parent_counter = 0; //to count the number of prints 
child_counter = 0;

//Parent should do this                  |        //Child should do this
while(1)                                 |while(1)
{                                        |
spin: if(parent_lock == LOCKED)          |spin: if(child_lock == LOCKED)
      {                                  |      {
         //spin till child unlocks you   |      //spin till parent unlocks you
          goto spin;                     |          goto spin;
      }                                  |      }
      else                               |      else
      {                                  |      {
          print("PARENT");               |          print("CHILD");
          parent_counter++;              |          child_counter++;
          //lock yourself allow the other|          //lock yourself allow the other
          parent_lock = LOCKED;          |          child_lock = LOCKED;
          child_lock = UNLOCKED;         |          parent_lock = UNLOCKED;
          if (parent_counter == 10)      |          if (child_counter == 10)
          {                              |          {
              break;//printed 10 times   |              break;     
          }                              |          }
       }                                 |       }
}                                        |}

//PARENT has printed 10times wait for    |//CHILD has printed 10times wait for 
//child                                  |// parent

PS:*我假设您可以自由地旋转我所做的锁,如果不是这种情况,您需要修改上述算法以进行睡眠和唤醒而不是旋转。
*您可以选择pthread锁原语来初始化parent_lock和child_lock。
*为了使程序正确,我们需要假设赋值语句是原子的 例如:child_lock = LOCKED 语句是原子的。

极其重要:请参阅父级中的顺序:

parent_lock = LOCKED;
child_lock = UNLOCKED;

及其在子线程中的对应部分。如果你交换这两行,那么你可能会死锁!!!!,因为父子混合执行的序列(由于 OS 调度程序)。

于 2013-10-29T15:18:24.157 回答
0

您可能需要更具体地了解要求。如果切换输出是唯一的实际要求,那么这样的事情应该可以工作(有点伪代码):

const char *strings[2] = { "Parent", "Child" };
pthread_mutex_t m; // needs to be properly initialized, of course
int which = 0;

thread_func()
{ while (1)
  { lock(&m);
    printf("%s\n", strings[which])
    which = !which;
    unlock(&m);
  }
}

您可以根据需要生成任意数量的线程,并且输出将继续交替。但是,线程不一定会一次交错一个迭代。尝试仅使用互斥锁且不使用 yield 函数(pthreads 未指定)获得正确的单次迭代交错有点困难......

于 2013-10-28T19:41:43.650 回答