信号量在C中锁定解决方案

时间:2012-10-11 17:22:16

标签: c synchronization semaphore locks

如何解决实现信号量同步的以下问题......

出于这个问题的目的,我们将如上所示对交叉点进行建模,将其划分为四分之一并识别每个四分之一哪条车道通过该部分进入交叉路口。 (只是为了澄清:我们正在道路的右侧行驶。)转弯通过交叉口的一个,两个或三个部分的进展来表示(为简单起见,假设在交叉路口没有发生U形转弯) 。因此,如果一辆汽车从北方驶入,取决于它的行驶位置,它会按如下方式穿过交叉路口:

        | ! + ^ |                   
        | ! + ! |
        | v + ! |
 --------------------------
   <----|NW + NE|  <----
        |   +   |
 ++++++++++++++++++++++++++                 
        |   +   |
  ----> |SW + SE| ---->
 --------------------------
        | ! + ^ |
        | ! + ! |
        | v + ! |



Right: NW
Straight: NW-SW
Left: NW-SW-SE 
到达十字路口的人首先进入。

同时没有两辆车可以在交叉路口的同一部分。 不要以同样的方式相互传递。如果两辆车都从同一方向接近并朝同一方向前进,那么到达交叉路口的第一辆车应该是第一辆到达目的地的车。同样,汽车不应该在交叉路口“跳跃”。例如,假设一辆汽车进入十字路口并直行。然后另一辆车从同一方向进入交叉路口并向左行驶。第二辆汽车应在第一辆汽车后退出十字路口。但是,假设汽车进入交叉路口并向左行驶。如果另一辆汽车从同一方向进入交叉路口并向右行驶,那么它可能会提前离开交叉路口,因为第一辆汽车即使在第二辆汽车前方也可能无法向左转弯。 每辆车在接近交叉路口(接近)时应打印一条消息,进入交叉路口的一个或多个区域((区域1),区域2和区域3),并离开交叉路口(离开),指示车辆号码,接近方向和目的地方向。

从给定方向接近交叉路口的汽车应以相同的顺序进入交叉路口。请注意,在汽车接近交叉路口之前应该没有同步以减慢它的速度。换句话说,不要简单地在进入交叉点的区域1之前打印接近,例如,在两个事件之间应该存在同步原语。 没有其他订购要求。例如,对于从不同方向接近的汽车没有订购要求。 我应该允许两辆或多辆汽车一次进入交叉路口,不允许来自任何方向的交通从任何其他方向挨饿。

createcars,它可以创建20辆汽车并将它们传递给接近交叉点,从而为每个车辆分配一个随机方向。我需要为它们分配一个随机的转弯方向;我也可以在接近交叉方向上做到这一点。

其他例程gostraight,turnright和turnleft可能有助于实现此解决方案,也可能没有帮助。我可以使用它们或丢弃它们。

以下是一辆从东方到达并驶向西方的汽车(汽车8)的示例输出。注意,区域(例如,区域1)是相对于每辆汽车定义的。右转的车将输出region1。直行的汽车将输出region1和region2。左转的车将输出region1,region2和region3。

approaching: car =  8, direction = E, destination = W
region1:     car =  8, direction = E, destination = W
region2:     car =  8, direction = E, destination = W
leaving:     car =  8, direction = E, destination = W

以下是我的例行程序..

    #include <types.h>
    #include <lib.h>
    #include <test.h>
    #include <thread.h>



    /*
    * Number of cars created.
    */

    #define NCARS 20


    /*
    *
    * Function Definitions
    *
    */

    static const char *directions[] = { "N", "E", "S", "W" };

    static const char *msgs[] = {
        "approaching:",
        "region1:    ",
        "region2:    ",
        "region3:    ",
        "leaving:    "
    };

    /* use these constants for the first parameter of message */
    enum { APPROACHING, REGION1, REGION2, REGION3, LEAVING };

    static void
    message(int msg_nr, int carnumber, int cardirection, int destdirection)
    {
        kprintf("%s car = %2d, direction = %s, destination = %s\n",
                msgs[msg_nr], carnumber,
                directions[cardirection], directions[destdirection]);
    }

    /*
    * gostraight()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement passing straight through the
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void gostraight(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * turnleft()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement making a left turn through the 
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void turnleft(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * turnright()
    *
    * Arguments:
    *      unsigned long cardirection: the direction from which the car
    *              approaches the intersection.
    *      unsigned long carnumber: the car id number for printing purposes.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      This function should implement making a right turn through the 
    *      intersection from any direction.
    *      Write and comment this function.
    */

    static void turnright(unsigned long cardirection, unsigned long carnumber)
    {
        /*
         * Avoid unused variable warnings.
         */

        (void) cardirection;
        (void) carnumber;
    }


    /*
    * approachintersection()
    *
    * Arguments: 
    *      void * unusedpointer: currently unused.
    *      unsigned long carnumber: holds car id number.
    *
    * Returns:
    *      nothing.
    *
    * Notes:
    *      I need to change this function to implement sempahore synchronization. These
    *      threads are created by createcars().  Each one must choose a direction
    *      randomly, approach the intersection, choose a turn randomly, and then
    *      complete that turn.  The code to choose a direction randomly is
    *      provided, the rest is left to you to implement.  Making a turn
    *      or going straight should be done by calling one of the functions
    *      above.
    */

    static void approachintersection(void * unusedpointer, unsigned long carnumber)
    {
        int cardirection;

        /*
         * Avoid unused variable and function warnings.
         */

        (void) unusedpointer;
        (void) carnumber;
    (void) gostraight;
    (void) turnleft;
    (void) turnright;

        /*
         * cardirection is set randomly.
         */

        cardirection = random() % 4;
    }


    /*
    * createcars()
    *
    * Arguments:
    *      int nargs: unused.
    *      char ** args: unused.
    *
    * Returns:
    *      0 on success.
    *
    * Notes:
    *       Driver code to start up the approachintersection() threads.
    *      I can modify this code as well for my solution..
    */

    int createcars(int nargs, char ** args)
    {
        int index, error;

        /*
         * Avoid unused variable warnings.
         */

        (void) nargs;
        (void) args;

        /*
         * Start NCARS approachintersection() threads.
         */

        for (index = 0; index < NCARS; index++) {

                error = thread_fork("approachintersection thread",
                                    NULL,
                                    index,
                                    approachintersection,
                                    NULL
                                    );

                /*
                 * panic() on error.
                 */

                if (error) {

                        panic("approachintersection: thread_fork failed: %s\n",
                              strerror(error)
                              );
                }
        }

        return 0;
    }

  [1]: http://i.stack.imgur.com/1389H.gif

1 个答案:

答案 0 :(得分:0)

考虑到你的十字路口只有四个区域,一辆车可能占用你需要四个信号量和四个线程来解决你的问题。无论汽车行驶方向如何,让我们将到达十字路口的所有汽车都放入单个FIFO队列。这将确保汽车按照到达顺序通过十字路口。然后每个线程从队列中拾取一辆汽车,确定路径并在路径中的第一个信号量上挂起。获取信号量后,它会检查这是否是路径中的最后一个区域,然后在汽车到达交叉路口的目的地边界时释放信号量。否则,线程会在其路径中的下一个信号量上挂起。获取下一个信号量后,它释放先前占用区域的信号量。当一个线程将汽车路由到过境边界时,它将从队列轮询中重新启动。

几个笔记。这种方法即使在U型转弯时也能正常工作。交通堵塞&#39;当我们在十字路口有4辆汽车并且每辆车都在等待下一个区域免费时,就像在现实生活中一样。您可以通过将线程数限制为三个来避免卡纸