gpt4 book ai didi

c - 模拟交叉点的线程锁

转载 作者:太空狗 更新时间:2023-10-29 15:04:28 25 4
gpt4 key购买 nike

我正在尝试使用线程和互斥锁来模拟交集。

我有走海峡、左转、右转的功能。现在,我有一个接近十字路口的功能。这会生成随机方向和转弯。每个线程共享接近的交叉点。

我已经为所有方向的所有汽车定义了所有锁。

走海峡功能。它有一个 switch 语句,只打印当时什么车在做什么。现在,我只是不确定要在此功能中锁定什么。如果汽车是朝北的方向,我会锁定东和西,与朝南的汽车一样向北行驶吗?

这是我的锁,它只是调用一个函数来锁定或解锁

#define NUMCARS 30

#define lock_NW(CAR) lock(CAR, NW_mutex)
#define lock_NE(CAR) lock(CAR, NE_mutex)
#define lock_SW(CAR) lock(CAR, SW_mutex)
#define lock_SE(CAR) lock(CAR, SE_mutex)

#define unlock_NW(CAR) unlock(CAR, NW_mutex)
#define unlock_NE(CAR) unlock(CAR, NE_mutex)
#define unlock_SW(CAR) unlock(CAR, SW_mutex)
#define unlock_SE(CAR) unlock(CAR, SE_mutex)

这是主要的

int main(int argc, char **argv){
/* Initial variables*/
int index, tid;
unsigned int carids[NUMCARS];
pthread_t carthreads[NUMCARS];

/* Start up a thread for each car*/
for(index = 0; index <NUMCARS; index++){
carids[index] = index;
tid = pthread_create(&carthreads[index], NULL, approachintersection, (void*)&carids[index]);
}

/* Wait for every car thread to finish */
for(index = 0; index <NUMCARS; index++){
pthread_join(carthreads[index], NULL);
}
printf("Done\n");
return 1;
}

这里是调用函​​数 going strait 的接近路口

static void * approachintersection(void* arg){
unsigned int * carnumberptr;
unsigned int carnumber;
orientation_t cardir = (orientation_t)random()%4;
unsigned long turn = random()%3;

carnumberptr = (unsigned int*) arg;
carnumber = (unsigned int) *carnumberptr;

if(turn==LEFT){
turnleft(cardir, carnumber);
} else if(turn==RIGHT){
turnright(cardir, carnumber);
} else {//straight
gostraight(cardir, carnumber);
}

return (void*)carnumberptr;
}

现在,这是我想锁定适当方向的 going strait 函数。

 /*
cardirection - The direction the car is pointing. If it is pointing NORTH,
it is starting from the South-Eastern corner of the intersection
and "going straight" means it wants to move SOUTH to NORTH.

valid options: NORTH, SOUTH, EAST, WEST

carnumber - The car identifier
*/


static void gostraight(orientation_t cardirection, unsigned int carnumber){

switch(cardirection){
case NORTH:
printf("Car %d, Moving South-North\n", carnumber);
break;
case SOUTH:
printf("Car %d, Moving North-South\n", carnumber);
break;
case EAST:
printf("Car %d, Moving West-East\n", carnumber);
break;
case WEST:
printf("Car %d, Moving East-West\n", carnumber);
break;
}
}

所以,如果接近的汽车从南指向北,那么这辆车就是 SE 汽车,我会用 lock_SE(CAR) 锁定东、西打印功能?阻止其他线程进入和打印?所以我会锁定解锁打印语句?

或者我会锁定整个 switch 语句吗?

** 编辑:这会是这样做的方式吗? **

static void turnleft(orientation_t cardirection, unsigned int carnumber){

int CAR;
CAR = carnumber;


switch(cardirection){
case NORTH:
lock_SE(CAR)
printf("Car %d, Moving South-West\n", carnumber);
unlock_SE(CAR)
break;
case SOUTH:
lock_NW(CAR)
printf("Car %d, Moving North-East\n", carnumber);
unlock_NW(CAR)
break;
case EAST:
lock_SW(CAR)
printf("Car %d, Moving West-North\n", carnumber);
unlock_SW(CAR)
break;
case WEST:
lock_NE(CAR)
printf("Car %d, Moving East-South\n", carnumber);
unlock_NE(CAR)
break;
}

最佳答案

这不是一个简单的问题。我将尝试展示两种解决方案。

首先是显而易见的:整个十字路口的一个互斥锁,在 turnleft, turnright, gostraight 的开头添加 lock(car, intersection_mutex);,就在每个函数结束时释放所述互斥量。这样一次只能让一辆车通过十字路口。这样做的好处是容易理解,不会导致死锁。缺点是一次只能有一辆车进入,但众所周知,两辆行驶在非交叉路径上的汽车可以毫无问题地进入。以下是 go_straight() 的示例(其他方法遵循相同的方法):

static void gostraight(orientation_t cardirection, unsigned int carnumber){
pthread_mutex_lock(&intersection_mutex);
switch(cardirection){
case NORTH:
printf("Car %d, Moving South-North\n", carnumber);
break;
case SOUTH:
printf("Car %d, Moving North-South\n", carnumber);
break;
case EAST:
printf("Car %d, Moving West-East\n", carnumber);
break;
case WEST:
printf("Car %d, Moving East-West\n", carnumber);
break;
}
}
pthread_mutex_unlock(&intersection_mutex);
}

要一次让多辆车进入,我们需要一种细粒度的方法。细粒度方法的问题是它更难实现和纠正。 go_straightturn_left 都需要锁定两个互斥体(你可以争辩说 turn left 需要三个......)。因此,如果您无法获得两个互斥量,则需要退后一步。将其转化为驾驶规则:

you must not enter the intersection before you can exit it. 

因此,要直走,我们必须首先获取离您最近的互斥量,然后是您路径中的下一个互斥量才能退出。如果我们不能同时获得两者,我们必须释放我们锁定的那个。如果我们不释放它,我们就会死锁。

为此,我将添加两个辅助函数:

static void lock_two(pthread_mutex_t *a, pthread_mutex_t *b) {
while(1) {
pthread_mutex_lock(a);
if(pthread_mutex_trylock(b) == 0)
break;
else
/* We must release the previously taken mutex so we don't dead lock the intersection */
pthread_mutex_unlock(a);
pthread_yield(); /* so we don't spin over lock/try-lock failed */
}
}
static void unlock_two(pthread_mutex_t *a, pthread_mutex_t *b) {
pthread_mutex_unlock(a);
pthread_mutex_unlock(b);
}

这是我的直走版本:

static void gostraight(orientation_t cardirection, unsigned int carnumber){  
switch(cardirection){
case NORTH:
lock_two(&SE_mutex, &NE_mutex);
printf("Car %d, Moving South-North\n", carnumber);
unlock_two(&SE_mutex, &NE_mutex);
break;
case SOUTH:
lock_two(&NW_mutex, &SW_mutex);
printf("Car %d, Moving North-South\n", carnumber);
unlock_two(&NW_mutex, &SW_mutex);
break;
case EAST:
lock_two(&SW_mutex, &SE_mutex);
printf("Car %d, Moving West-East\n", carnumber);
unlock_two(&SW_mutex, &SE_mutex);
break;
case WEST:
lock_two(&NE_mutex, &NW_mutex);
printf("Car %d, Moving East-West\n", carnumber);
unlock_two(&NE_mutex, &NW_mutex);
break;
}
}

turn_left 然后需要遵循相同的方法。

关于c - 模拟交叉点的线程锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13573831/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com