/* * 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. * * 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. * * 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. * * 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. * * 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. */ #include #include #include #include #include #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); } return NULL; } void *dec() { for (int i = 0; i < loop; i++) { pthread_mutex_lock(&mutex); gv--; pthread_mutex_unlock(&mutex); } return NULL; } 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; for (i = 0; i < 3; i++) { printf("+"); usleep(interval); 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(); pthread_create(&thread[i], NULL, &plus, (void *) t); pthread_create(&thread[i + 1], NULL, &minus, NULL); pthread_join(thread[i], NULL); pthread_join(thread[i + 1], NULL); } sem_destroy(&sem); return 0; }