Posix 线程与互斥体同步
Posix threads synchronization with mutexes
我越是尝试学习这个东西,就越是感到困惑,所以我乐于接受任何建议和帮助。谢谢。程序是关于窄桥(mutex)和上面运行宁车(进程),但一次只有一个进程可以通过它。桥接线程穿越后可以将自己加入队列,也可以到自己休眠的城市加入队列。进程(汽车)需要 运行 直到程序终止。如有必要,我可以将代码翻译成英文。编译后 运行 是这样的:./program -n -debug
n - 线程数,调试 - 打印队列,仅可选。我认为线程不能同步工作,例如我 运行ned 程序有 8 个线程并且队列中有 34 号线程。不知道为什么,它发生在我 "fixed" 代码之后。
/*
There's a road(bridge) from city A to B. Only one car can use it to move at a time.
Cars should run( change cities ) all the time, no end of program.
Access to the bridge should be synchronized with mutexes. Every car have its numer from 1 to N where N is given as first parameter.
Program should printing something like this when one of printing variable is changing:
A - 5 10 >> >[>> 4 >> ] << <4 6 - B
@up That means that in city A is 5 cars, in city A queue is 10 cars ( wanting to change city ). Thread with numer 4 is changing city from A to B. In city B queue is 4 cars and in city B is 6 cars.
If second parameter -debug is given, then program should printf queue status.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define true 1
#define false 0
pthread_mutex_t countOfQueueA;
pthread_mutex_t countOfQueueB;
pthread_mutex_t bridge;
pthread_mutex_t queueA;
pthread_mutex_t queueB;
pthread_mutex_t cityA;
pthread_mutex_t cityB;
int inQueueA = 0; // Number of cars in queue of city A
int inQueueB = 0; // Number of cars in queue of city B
int inCityA = 0; // Number of cars in city A
int inCityB = 0; // Number of cars in city B
int createdThreads = 0; // Number of created threads by pthread_create
int numberOfCars = 0; //
int debugMode = 0; // 0 - no, 1 - debug
int *queueInA; // Pointer to queue in city A
int *queueInB; // Pointer to queue in city B
void printQueue(char city)
{
int i;
if (city == 'a')
{
printf("\nQueue A status: ");
for (i = 0; i<numberOfCars; i++)
{
printf("%d ", queueInA[i]);
}
printf("\n");
}
else if (city == 'b')
{
printf("\nQueue B status: ");
for (i = 0; i<numberOfCars; i++)
{
printf("%d ", queueInB[i]);
}
printf("\n");
}
}
void addToQueue(char city, int threadNumber) // Adding at the end of the queue in selected city
{
if (city == 'a')
{
pthread_mutex_lock(&queueA);
pthread_mutex_lock(&countOfQueueA);
int i = 0;
while (queueInA[i] != 0) //Looking for first free place = 0 to add car
{
i++;
}
queueInA[i] = threadNumber;
inQueueA++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
pthread_mutex_unlock(&queueA);
pthread_mutex_unlock(&countOfQueueA);
}
else if (city == 'b')
{
pthread_mutex_lock(&queueB);
pthread_mutex_lock(&countOfQueueB);
int i = 0;
while (queueInB[i] != 0)
{
i++;
}
queueInB[i] = threadNumber;
inQueueB++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
pthread_mutex_unlock(&queueB);
pthread_mutex_unlock(&countOfQueueB);
}
}
void changeCity2(int threadNumber, char city)
{
if (city == 'a')
{
while (queueInA[0] != threadNumber);// Oczekiwanie dopoki samochod nie jest 1szy w kolejce
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [>> %d >>] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
city = 'b';
pthread_mutex_unlock(&bridge);
sleep(2); // Sleeping for simulating "working" time
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
else if (city == 'b')
{
while (queueInB[0] != threadNumber); // Oczekiwanie dopoki samochod nie jest 1szy w kolejce
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [<< %d <<] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
city = 'a';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
}
void runIntoCity(int threadNumber, char city)
{
if (city == 'a')
{
pthread_mutex_lock(&cityA);
inCityA++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
pthread_mutex_unlock(&cityA);
sleep(3);
pthread_mutex_lock(&cityA);
inCityA--;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
pthread_mutex_unlock(&cityA);
}
else
{
pthread_mutex_lock(&cityB);
inCityB++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
pthread_mutex_unlock(&cityB);
sleep(3);
pthread_mutex_lock(&cityB);
inCityB--;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
pthread_mutex_unlock(&cityB);
}
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
void removeFromQueue(char city, int threadNumber) // Removing car from queue if its 1st in queue
{
if (city == 'a') // Car being removed from queue of city A
{
pthread_mutex_lock(&queueA);
pthread_mutex_lock(&countOfQueueA);
if (queueInA[0] == threadNumber)
{
inQueueA--;
int i = 1;
while (queueInA[i] != 0)
{
queueInA[i - 1] = queueInA[i];
i++;
}
queueInA[i - 1] = 0;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
}
else printf("Car is not first in queue. Error!");
pthread_mutex_unlock(&queueA);
pthread_mutex_unlock(&countOfQueueA);
}
else if (city == 'b')
{
pthread_mutex_lock(&queueB);
pthread_mutex_lock(&countOfQueueB);
if (queueInB[0] == threadNumber)
{
inQueueB--;
int i = 1;
while (queueInB[i] != 0)
{
queueInB[i - 1] = queueInB[i];
i++;
}
queueInB[i - 1] = 0;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
}
else printf("Samochod nie jest pierwszy w kolejce. BLAD W KODZIE!");
pthread_mutex_unlock(&queueB);
pthread_mutex_unlock(&countOfQueueB);
}
}
void changeCity(int threadNumber, char city)
{
if (city == 'a')
{
while (queueInA[0] != threadNumber); // Waiting until car is ready to change city - it's first in queue
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [>> %d >>] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
city = 'b';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
else if (city == 'b')
{
while (queueInB[0] != threadNumber); // Waiting until car is ready to change city - it's first in queue
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [<< %d <<] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
city = 'a';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
}
char cityDraw() // Being used at start of thread to attach threads to cities
{
int randomNumber = rand() % 100;
int randomNumber2 = rand() % randomNumber;
if (randomNumber2 % 2 == 0)
{
return 'a';
}
else
{
return 'b';
}
}
void *threadInitiate(int threadNumber)
{
char city = cityDraw();
addToQueue(city, threadNumber);
while (inQueueA + inQueueB < numberOfCars); // Waiting for all threads to get run by pthread_create
changeCity(threadNumber, city);
}
void createThreads()
{
pthread_t car[numberOfCars];
int i;
for (i = 0; i < numberOfCars; i++)
{
int wynik = pthread_create(&car[i], NULL, &threadInitiate, (void *)i + 1); //!!!!!!!!!!!!!
if (wynik != 0) printf("Pthread_create failed\n");
else createdThreads++;
}
for (i = 0; i < numberOfCars; i++)
{
pthread_join(car[i], NULL);
}
}
void initiateQueues() // Making every elem. of queues became 0. Just to be sure. Thread numbers are starting from number 1.
{
int i;
for (i = 0; i<numberOfCars; i++)
{
queueInA[i] = 0;
queueInB[i] = 0;
}
}
int checkNumberOfCars(char *arg) // Parsing and converting to int, numer of cars from parameter
{
int argSize = 1;
while (arg[argSize] != '[=11=]')
{
argSize++;
}
char temp[argSize];
int indArg = 1;
int indTemp = 0;
for (indArg = 1; indArg<argSize; indArg++)
{
temp[indTemp] = arg[indArg];
indTemp++;
}
temp[indTemp] = '[=11=]';
int ls = atoi(temp);
return ls;
}
int debugCheck(int argc, char **argv) // Checking if -debug parameter is given
{
if (argc>2)
{
if (strcmp(argv[2], "-debug") == 0)
return true;
else
return false;
}
}
int main(int argc, char **argv)
{
numberOfCars = checkNumberOfCars(argv[1]);
printf("\nNumber of cars from param = %d", numberOfCars);
debugMode = debugCheck(argc, argv);
if (debugMode == 1) printf("\nDebugMode is ON - writing queues status on every change");
int queueArrayA[numberOfCars];
int queueArrayB[numberOfCars];
queueInA = queueArrayA;
queueInB = queueArrayB;
initiateQueues();
pthread_mutex_init(&bridge, NULL);
pthread_mutex_init(&queueA, NULL);
pthread_mutex_init(&queueB, NULL);
pthread_mutex_init(&cityA, NULL);
pthread_mutex_init(&cityB, NULL);
pthread_mutex_init(&countOfQueueA, NULL);
pthread_mutex_init(&countOfQueueB, NULL);
createThreads();
return 0;
}
这看起来像是并发编程课程的作业。这段代码有很多问题,我认为不值得尝试找出错误,因为你不会为此得到任何分数,而且无论如何都必须重写。以下是大致按重要性排序的问题。
队列的用途是什么?汽车线程应该都尝试锁定互斥量。您的程序中不需要队列 - 等待互斥锁的线程队列由操作系统在幕后管理。汽车线程可能应该做这样的事情:
pthread_mutex_lock(&bridge);
// remove car from city of origin
// no need for mutex, because only one car can be on the bridge at once,
// so only the car on the bridge will modify the car count fields in cities
city[i].cars--;
sleep(/* some time */);
// add car to destination city
city[1-i].cars++;
pthread_mutex_unlock(&bridge);
sleep(/* some time */);
- 汽车线程将永远运行,但它们会不断地递归调用越来越多的函数。这最终会炸毁堆栈。将汽车线程函数编写为显式无限循环。没有物理计算机可以让您拥有无限深度的调用图。
- 大量重复代码。一切都写了两次,一次写给城市'a',第二次写给城市'b'。利用数组并将数字 0 分配给一个城市,将 1 分配给另一个城市,这样您就可以执行类似
city[1-i].car_count++
. 的操作
- 管理队列数据结构的代码(例如,找到一个空 space、从队列中删除一辆车,等等)与其他不相关的代码混合在一起。如果你真的需要那些我怀疑的队列,写一个
struct car_queue
和添加和删除汽车的操作,而不是直接在函数changeCity2
、addToQueue
等函数中编写队列操作.
- 不必要的互斥锁。例如,
countofQueueA
和 queueA
应该组合成一个互斥量。事实上,可能应该只有三个互斥体:城市 A、城市 B 和桥梁。它甚至可以只用一个桥接互斥锁来完成。
- 你为什么要
rand() % 4
然后马上 % 2
结果呢?没意义,马上rand() % 2
cityDraw
中的双重随机化完全没有意义,给您的结果略有偏差。例如,如果你在第一行得到 0,你将在第二行得到 0、1 或 2,所以汽车将有 2/3 的机会去 A 城市。如果你在第一行得到 0线,不管你在第二个得到什么,车都会去城市A。就做 rand() % 2
.
- 永远不要做类似
#define true 1
的事情——这只是引入了与 C++ 的无故不兼容。相反,使用 #include <stdlib.h>
并写入 TRUE
和 FALSE
.
我越是尝试学习这个东西,就越是感到困惑,所以我乐于接受任何建议和帮助。谢谢。程序是关于窄桥(mutex)和上面运行宁车(进程),但一次只有一个进程可以通过它。桥接线程穿越后可以将自己加入队列,也可以到自己休眠的城市加入队列。进程(汽车)需要 运行 直到程序终止。如有必要,我可以将代码翻译成英文。编译后 运行 是这样的:./program -n -debug n - 线程数,调试 - 打印队列,仅可选。我认为线程不能同步工作,例如我 运行ned 程序有 8 个线程并且队列中有 34 号线程。不知道为什么,它发生在我 "fixed" 代码之后。
/*
There's a road(bridge) from city A to B. Only one car can use it to move at a time.
Cars should run( change cities ) all the time, no end of program.
Access to the bridge should be synchronized with mutexes. Every car have its numer from 1 to N where N is given as first parameter.
Program should printing something like this when one of printing variable is changing:
A - 5 10 >> >[>> 4 >> ] << <4 6 - B
@up That means that in city A is 5 cars, in city A queue is 10 cars ( wanting to change city ). Thread with numer 4 is changing city from A to B. In city B queue is 4 cars and in city B is 6 cars.
If second parameter -debug is given, then program should printf queue status.
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#define true 1
#define false 0
pthread_mutex_t countOfQueueA;
pthread_mutex_t countOfQueueB;
pthread_mutex_t bridge;
pthread_mutex_t queueA;
pthread_mutex_t queueB;
pthread_mutex_t cityA;
pthread_mutex_t cityB;
int inQueueA = 0; // Number of cars in queue of city A
int inQueueB = 0; // Number of cars in queue of city B
int inCityA = 0; // Number of cars in city A
int inCityB = 0; // Number of cars in city B
int createdThreads = 0; // Number of created threads by pthread_create
int numberOfCars = 0; //
int debugMode = 0; // 0 - no, 1 - debug
int *queueInA; // Pointer to queue in city A
int *queueInB; // Pointer to queue in city B
void printQueue(char city)
{
int i;
if (city == 'a')
{
printf("\nQueue A status: ");
for (i = 0; i<numberOfCars; i++)
{
printf("%d ", queueInA[i]);
}
printf("\n");
}
else if (city == 'b')
{
printf("\nQueue B status: ");
for (i = 0; i<numberOfCars; i++)
{
printf("%d ", queueInB[i]);
}
printf("\n");
}
}
void addToQueue(char city, int threadNumber) // Adding at the end of the queue in selected city
{
if (city == 'a')
{
pthread_mutex_lock(&queueA);
pthread_mutex_lock(&countOfQueueA);
int i = 0;
while (queueInA[i] != 0) //Looking for first free place = 0 to add car
{
i++;
}
queueInA[i] = threadNumber;
inQueueA++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
pthread_mutex_unlock(&queueA);
pthread_mutex_unlock(&countOfQueueA);
}
else if (city == 'b')
{
pthread_mutex_lock(&queueB);
pthread_mutex_lock(&countOfQueueB);
int i = 0;
while (queueInB[i] != 0)
{
i++;
}
queueInB[i] = threadNumber;
inQueueB++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
pthread_mutex_unlock(&queueB);
pthread_mutex_unlock(&countOfQueueB);
}
}
void changeCity2(int threadNumber, char city)
{
if (city == 'a')
{
while (queueInA[0] != threadNumber);// Oczekiwanie dopoki samochod nie jest 1szy w kolejce
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [>> %d >>] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
city = 'b';
pthread_mutex_unlock(&bridge);
sleep(2); // Sleeping for simulating "working" time
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
else if (city == 'b')
{
while (queueInB[0] != threadNumber); // Oczekiwanie dopoki samochod nie jest 1szy w kolejce
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [<< %d <<] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
city = 'a';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
}
void runIntoCity(int threadNumber, char city)
{
if (city == 'a')
{
pthread_mutex_lock(&cityA);
inCityA++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
pthread_mutex_unlock(&cityA);
sleep(3);
pthread_mutex_lock(&cityA);
inCityA--;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
pthread_mutex_unlock(&cityA);
}
else
{
pthread_mutex_lock(&cityB);
inCityB++;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
pthread_mutex_unlock(&cityB);
sleep(3);
pthread_mutex_lock(&cityB);
inCityB--;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
pthread_mutex_unlock(&cityB);
}
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
void removeFromQueue(char city, int threadNumber) // Removing car from queue if its 1st in queue
{
if (city == 'a') // Car being removed from queue of city A
{
pthread_mutex_lock(&queueA);
pthread_mutex_lock(&countOfQueueA);
if (queueInA[0] == threadNumber)
{
inQueueA--;
int i = 1;
while (queueInA[i] != 0)
{
queueInA[i - 1] = queueInA[i];
i++;
}
queueInA[i - 1] = 0;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
}
else printf("Car is not first in queue. Error!");
pthread_mutex_unlock(&queueA);
pthread_mutex_unlock(&countOfQueueA);
}
else if (city == 'b')
{
pthread_mutex_lock(&queueB);
pthread_mutex_lock(&countOfQueueB);
if (queueInB[0] == threadNumber)
{
inQueueB--;
int i = 1;
while (queueInB[i] != 0)
{
queueInB[i - 1] = queueInB[i];
i++;
}
queueInB[i - 1] = 0;
printf("\nA-%d %d>>> [ BLANK ] <<<%d %d-B", inCityA, inQueueA, inQueueB, inCityB);
if (debugMode == 1)
{
printQueue(city);
}
}
else printf("Samochod nie jest pierwszy w kolejce. BLAD W KODZIE!");
pthread_mutex_unlock(&queueB);
pthread_mutex_unlock(&countOfQueueB);
}
}
void changeCity(int threadNumber, char city)
{
if (city == 'a')
{
while (queueInA[0] != threadNumber); // Waiting until car is ready to change city - it's first in queue
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [>> %d >>] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueA);
printQueue(city);
pthread_mutex_unlock(&queueA);
}
city = 'b';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
else if (city == 'b')
{
while (queueInB[0] != threadNumber); // Waiting until car is ready to change city - it's first in queue
pthread_mutex_lock(&bridge);
removeFromQueue(city, threadNumber);
printf("\nA-%d %d>>> [<< %d <<] <<<%d %d-B", inCityA, inQueueA, threadNumber, inQueueB, inCityB);
if (debugMode == 1)
{
pthread_mutex_lock(&queueB);
printQueue(city);
pthread_mutex_unlock(&queueB);
}
city = 'a';
pthread_mutex_unlock(&bridge);
sleep(2);
int randomNumber = rand() % 4;
if (randomNumber % 2 == 0)
{
addToQueue(city, threadNumber);
changeCity2(threadNumber, city);
}
else
{
runIntoCity(threadNumber, city);
}
}
}
char cityDraw() // Being used at start of thread to attach threads to cities
{
int randomNumber = rand() % 100;
int randomNumber2 = rand() % randomNumber;
if (randomNumber2 % 2 == 0)
{
return 'a';
}
else
{
return 'b';
}
}
void *threadInitiate(int threadNumber)
{
char city = cityDraw();
addToQueue(city, threadNumber);
while (inQueueA + inQueueB < numberOfCars); // Waiting for all threads to get run by pthread_create
changeCity(threadNumber, city);
}
void createThreads()
{
pthread_t car[numberOfCars];
int i;
for (i = 0; i < numberOfCars; i++)
{
int wynik = pthread_create(&car[i], NULL, &threadInitiate, (void *)i + 1); //!!!!!!!!!!!!!
if (wynik != 0) printf("Pthread_create failed\n");
else createdThreads++;
}
for (i = 0; i < numberOfCars; i++)
{
pthread_join(car[i], NULL);
}
}
void initiateQueues() // Making every elem. of queues became 0. Just to be sure. Thread numbers are starting from number 1.
{
int i;
for (i = 0; i<numberOfCars; i++)
{
queueInA[i] = 0;
queueInB[i] = 0;
}
}
int checkNumberOfCars(char *arg) // Parsing and converting to int, numer of cars from parameter
{
int argSize = 1;
while (arg[argSize] != '[=11=]')
{
argSize++;
}
char temp[argSize];
int indArg = 1;
int indTemp = 0;
for (indArg = 1; indArg<argSize; indArg++)
{
temp[indTemp] = arg[indArg];
indTemp++;
}
temp[indTemp] = '[=11=]';
int ls = atoi(temp);
return ls;
}
int debugCheck(int argc, char **argv) // Checking if -debug parameter is given
{
if (argc>2)
{
if (strcmp(argv[2], "-debug") == 0)
return true;
else
return false;
}
}
int main(int argc, char **argv)
{
numberOfCars = checkNumberOfCars(argv[1]);
printf("\nNumber of cars from param = %d", numberOfCars);
debugMode = debugCheck(argc, argv);
if (debugMode == 1) printf("\nDebugMode is ON - writing queues status on every change");
int queueArrayA[numberOfCars];
int queueArrayB[numberOfCars];
queueInA = queueArrayA;
queueInB = queueArrayB;
initiateQueues();
pthread_mutex_init(&bridge, NULL);
pthread_mutex_init(&queueA, NULL);
pthread_mutex_init(&queueB, NULL);
pthread_mutex_init(&cityA, NULL);
pthread_mutex_init(&cityB, NULL);
pthread_mutex_init(&countOfQueueA, NULL);
pthread_mutex_init(&countOfQueueB, NULL);
createThreads();
return 0;
}
这看起来像是并发编程课程的作业。这段代码有很多问题,我认为不值得尝试找出错误,因为你不会为此得到任何分数,而且无论如何都必须重写。以下是大致按重要性排序的问题。
队列的用途是什么?汽车线程应该都尝试锁定互斥量。您的程序中不需要队列 - 等待互斥锁的线程队列由操作系统在幕后管理。汽车线程可能应该做这样的事情:
pthread_mutex_lock(&bridge); // remove car from city of origin // no need for mutex, because only one car can be on the bridge at once, // so only the car on the bridge will modify the car count fields in cities city[i].cars--; sleep(/* some time */); // add car to destination city city[1-i].cars++; pthread_mutex_unlock(&bridge); sleep(/* some time */);
- 汽车线程将永远运行,但它们会不断地递归调用越来越多的函数。这最终会炸毁堆栈。将汽车线程函数编写为显式无限循环。没有物理计算机可以让您拥有无限深度的调用图。
- 大量重复代码。一切都写了两次,一次写给城市'a',第二次写给城市'b'。利用数组并将数字 0 分配给一个城市,将 1 分配给另一个城市,这样您就可以执行类似
city[1-i].car_count++
. 的操作
- 管理队列数据结构的代码(例如,找到一个空 space、从队列中删除一辆车,等等)与其他不相关的代码混合在一起。如果你真的需要那些我怀疑的队列,写一个
struct car_queue
和添加和删除汽车的操作,而不是直接在函数changeCity2
、addToQueue
等函数中编写队列操作. - 不必要的互斥锁。例如,
countofQueueA
和queueA
应该组合成一个互斥量。事实上,可能应该只有三个互斥体:城市 A、城市 B 和桥梁。它甚至可以只用一个桥接互斥锁来完成。 - 你为什么要
rand() % 4
然后马上% 2
结果呢?没意义,马上rand() % 2
cityDraw
中的双重随机化完全没有意义,给您的结果略有偏差。例如,如果你在第一行得到 0,你将在第二行得到 0、1 或 2,所以汽车将有 2/3 的机会去 A 城市。如果你在第一行得到 0线,不管你在第二个得到什么,车都会去城市A。就做rand() % 2
.- 永远不要做类似
#define true 1
的事情——这只是引入了与 C++ 的无故不兼容。相反,使用#include <stdlib.h>
并写入TRUE
和FALSE
.