Я пытаюсь решить классическую проблему семафора / мьютекса в «однополосном туннеле».Это код, который я написал, но он не работает, и я не могу понять, почему.Теоретически, автомобили, идущие в противоположном направлении, должны пересекаться ТОЛЬКО, если туннель уже используется автомобилями, движущимися в том же направлении, в противном случае они должны ждать, результат должен быть примерно таким:
car1_leftToRight crossing
car2_leftToRight crossing
car1_leftToRight end crossing
car2_leftToRight end crossing (ALL cars leftToRight have crossed)
car1_rightToLeft start crossing
etc..
, но мой текущий выходэто тот, который вы можете увидеть на картинке, которую я прикрепил.Я также создал глобальную переменную (globalCarsCrossing), чтобы отслеживать, сколько автомобилей в настоящее время пересекает мост, и, как вы можете видеть, кажется, что автомобили с противоположных направлений пересекаются одновременно!
Есть ли у вас какие-либо предположения о том, что я делаю неправильно?
#define UNICODE
#define _UNICODE
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <WinBase.h>
#include <process.h> //include for function _beginthreadex
int globalCarsCrossing = 0;
typedef struct {
int numTraversingCar;
int crossingTime;
int arrivalTime; //0 - arrivalTime -> random number, how much time pass between cars arrival
HANDLE mutex;
LPHANDLE bridgeMutexPtr;
int direction;
} ThParams;
DWORD WINAPI thFunction(LPVOID thParamsPtr);
void crossBridge();
int _tmain(int argc, LPTSTR argv[])
{
int timeL2R, timeR2L, timeARRIVAL, nL2R, nR2L;
LPHANDLE thL2Rarray, thR2Larray;
ThParams paramsL2R, paramsR2L;
HANDLE bridgeMutex;
if (argc < 6)
{
_ftprintf(stderr, _T("missing parameters: <timeL2R> <timeR2L> <timeARRIVAL> <nL2R> <nR2L>\n"));
exit(EXIT_FAILURE);
}
timeL2R = _ttoi(argv[1]); //WINDOWS version of "atoi"
timeR2L = _ttoi(argv[2]);
timeARRIVAL = _ttoi(argv[3]);
nL2R = _ttoi(argv[4]);
nR2L = _ttoi(argv[5]);
//allocates all threads array
thL2Rarray = (LPHANDLE)malloc(nL2R * sizeof(HANDLE));
thR2Larray = (LPHANDLE)malloc(nR2L * sizeof(HANDLE));
//initialize all parameters
bridgeMutex = CreateMutex(NULL, FALSE, NULL);
//create structs for threads
paramsL2R.mutex = CreateMutex(NULL, FALSE, NULL);
paramsL2R.bridgeMutexPtr = &bridgeMutex;
paramsL2R.arrivalTime = timeARRIVAL;
paramsL2R.numTraversingCar = 0;
paramsL2R.crossingTime = timeL2R;
paramsL2R.direction = 0;
//paramsR2L.criticalSectionPtr = &criticalSectionR2L;
paramsR2L.mutex = CreateMutex(NULL, FALSE, NULL);
paramsR2L.bridgeMutexPtr = &bridgeMutex;
paramsR2L.arrivalTime = timeARRIVAL;
paramsR2L.numTraversingCar = 0;
paramsR2L.crossingTime = timeR2L;
paramsR2L.direction = 1;
//create L2R threads
for (int i = 0; i<nL2R; i++)
thL2Rarray[i] = CreateThread(NULL, 0, thFunction, ¶msL2R, 0, NULL);
//create R2L threads
for (int i = 0; i<nR2L; i++)
thR2Larray[i] = CreateThread(NULL, 0, thFunction, ¶msR2L, 0, NULL);
//wait for ALL threads to return
WaitForMultipleObjects(nL2R, thL2Rarray, TRUE, INFINITE);
WaitForMultipleObjects(nR2L, thR2Larray, TRUE, INFINITE);
_tprintf(_T("all threads are returned\n"));
//closa all thread handle
for (int i = 0; i<nL2R; i++)
CloseHandle(thL2Rarray[i]);
for (int i = 0; i<nR2L; i++)
CloseHandle(thR2Larray[i]);
////free and release everything
free(thL2Rarray);
free(thR2Larray);
CloseHandle(bridgeMutex);
CloseHandle(paramsR2L.mutex);
CloseHandle(paramsL2R.mutex);
return 0;
}
DWORD WINAPI thFunction(LPVOID thParamsPtr)
{
ThParams *paramsPtr = (ThParams *)thParamsPtr;
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar + 1;
if (paramsPtr->numTraversingCar == 1)
WaitForSingleObject(*(paramsPtr->bridgeMutexPtr), INFINITE);
globalCarsCrossing++;
_tprintf(_T("%d crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING: %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
ReleaseMutex(paramsPtr->mutex);
crossBridge();
WaitForSingleObject(paramsPtr->mutex, INFINITE);
paramsPtr->numTraversingCar = paramsPtr->numTraversingCar - 1;
globalCarsCrossing--;
_tprintf(_T("%d end crossing direction: %d, TOT_cars_from_this_direction: %d, GLOBAL_CARS_CROSSING %d\n"), GetCurrentThreadId(), paramsPtr->direction, paramsPtr->numTraversingCar, globalCarsCrossing);
if (paramsPtr->numTraversingCar == 0) {
_tprintf(_T("RELEASED\n"));
ReleaseMutex(*(paramsPtr->bridgeMutexPtr));
}
ReleaseMutex(paramsPtr->mutex);
return 0;
}