2023-10-24 16:53:50 -03:00
|
|
|
/*
|
2023-10-25 12:08:03 -03:00
|
|
|
* Question 2: You see the number 1 most of the time. It is sometimes different because there are periods of time when
|
|
|
|
* the threads are reading/writing to the same place, but with the number of increments being 100, it is not likely that
|
|
|
|
* the threads will be reading/writing at the same time. In the CPU what happens is that a value is loaded into a
|
|
|
|
* register, while another thread completes a task, and then the value is written back to the memory. This leads to
|
|
|
|
* missing increments/decrements.
|
2023-10-24 16:53:50 -03:00
|
|
|
*
|
2023-10-25 12:08:03 -03:00
|
|
|
* Question 4: You see the number 1 often. Since the number of increments is 1000, the chance has increased for threads
|
|
|
|
* to be reading/writing at the same time. This leads to more missing increments/decrements.
|
2023-10-24 16:53:50 -03:00
|
|
|
*
|
2023-10-25 12:08:03 -03:00
|
|
|
* Question 6: You see the number 1 almost never. The number of loops at this point almost guarantees that the threads
|
|
|
|
* will be reading/writing at the same time, and the counter missing increments/decrements.
|
2023-10-24 16:53:50 -03:00
|
|
|
*
|
2023-10-25 12:08:03 -03:00
|
|
|
* Question 8: The number 1 is the only thing displayed. This is because the mutex lock ensures that the threads will
|
|
|
|
* not be reading/writing at the same time, and the counter will not miss increments/decrements. When another thread
|
|
|
|
* tried to lock the mutex, it waits for it to first become unlocked, ensuring proper thread synchronization.
|
2023-10-25 11:27:26 -03:00
|
|
|
*
|
2023-10-25 12:08:03 -03:00
|
|
|
* Question 13: The program no longer finishes, because the semaphore is waiting for the other thread to increment it,
|
|
|
|
* but the other thread finishes incrementing it before the first thread gets the chance to print more than 3 times.
|
|
|
|
* The minus function prints twice at the end because the print comes before the semaphore wait, so there is one minus
|
|
|
|
* for each plus, plus one minus before it has to wait for the semaphore. This situation is called a deadlock.
|
2023-10-24 16:53:50 -03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include<pthread.h>
|
|
|
|
#include<stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <semaphore.h>
|
|
|
|
|
|
|
|
#define RANDOM_WITHIN_RANGE(a, b, seed) (rand_r(&seed)%b+a)
|
|
|
|
|
|
|
|
int gv = 1;
|
|
|
|
pthread_mutex_t mutex;
|
|
|
|
sem_t sem;
|
|
|
|
|
|
|
|
#define loop 10000
|
|
|
|
|
|
|
|
void *inc() {
|
|
|
|
for (int i = 0; i < loop; i++) {
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
gv++;
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
}
|
2023-10-25 11:27:26 -03:00
|
|
|
return NULL;
|
2023-10-24 16:53:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void *dec() {
|
|
|
|
for (int i = 0; i < loop; i++) {
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
gv--;
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
}
|
2023-10-25 11:27:26 -03:00
|
|
|
return NULL;
|
2023-10-24 16:53:50 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void *minus() {
|
|
|
|
int i = 0;
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
|
|
printf("-");
|
|
|
|
sem_wait(&sem);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *plus(void *argg) {
|
|
|
|
unsigned int seed = *((unsigned int *) argg);
|
|
|
|
int interval = RANDOM_WITHIN_RANGE(100000, 500000, seed);
|
|
|
|
int i = 0;
|
|
|
|
|
2023-10-25 12:08:03 -03:00
|
|
|
for (i = 0; i < 3; i++) {
|
2023-10-24 16:53:50 -03:00
|
|
|
printf("+");
|
2023-10-25 11:27:26 -03:00
|
|
|
usleep(interval);
|
2023-10-24 16:53:50 -03:00
|
|
|
sem_post(&sem);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
// Init Mutex
|
|
|
|
pthread_mutex_init(&mutex, NULL);
|
|
|
|
// Create thread pool and run threads
|
|
|
|
pthread_t thread[2];
|
|
|
|
pthread_create(&thread[i], NULL, &inc, NULL);
|
|
|
|
pthread_create(&thread[i + 1], NULL, &dec, NULL);
|
|
|
|
// Wait for threads to finish
|
|
|
|
pthread_join(thread[i], NULL);
|
|
|
|
pthread_join(thread[i + 1], NULL);
|
|
|
|
// Destroy Mutex
|
|
|
|
pthread_mutex_destroy(&mutex);
|
|
|
|
// Print final value
|
|
|
|
printf("%d\n", gv);
|
|
|
|
|
|
|
|
// Init Semaphore
|
|
|
|
sem_init(&sem, 0, 0);
|
|
|
|
for (i = 0; i < 1; i++) {
|
|
|
|
unsigned int *t = (unsigned int *) malloc(sizeof(unsigned int));
|
|
|
|
*t = rand();
|
|
|
|
|
2023-10-25 11:27:26 -03:00
|
|
|
pthread_create(&thread[i], NULL, &plus, (void *) t);
|
|
|
|
pthread_create(&thread[i + 1], NULL, &minus, NULL);
|
2023-10-24 16:53:50 -03:00
|
|
|
|
|
|
|
pthread_join(thread[i], NULL);
|
|
|
|
pthread_join(thread[i + 1], NULL);
|
|
|
|
}
|
|
|
|
sem_destroy(&sem);
|
|
|
|
|
|
|
|
return 0;
|
2023-10-25 12:08:03 -03:00
|
|
|
}
|