Comp111: Operating Systems
Classroom Exercise 8
Fall 2018

group member 1: ____________________________ login: ______________
group member 2: ____________________________ login: ______________
group member 3: ____________________________ login: ______________
group member 4: ____________________________ login: ______________
group member 5: ____________________________ login: ______________
group member 6: ____________________________ login: ______________
group member 7: ____________________________ login: ______________
group member 8: ____________________________ login: ______________

In class we have discussed the basic pattern of thread execution, including shared memory. The exercise refers to the code:

int x=0; 
void *threaded_routine (void * v) { 
    const int *n = (int *)v; 
    int i; 
    for (i=0; i<10; i++)  { 
        int y=x; y++; sleep(1); x=y; 
        printf("%d: x=%d\n",*n,x); 
  1. What happens when we execute 10 instances of this code in parallel, in shared memory threads?

  2. What happens if we instead surround the whole routine with pthread_mutex_lock and Pthread_mutex_unlock before executing 10 instances?

  3. What would happen if we removed the sleep call and executed 10 instances?
  4. Suppose that the sleep has been removed. Where would you put the pthread_mutex_lock and pthread_mutex_unlock so that all increments would be preserved while completing multiple threads as quickly as possible?

  5. (Advanced) I claim that in using locks, one thread running alone will never call the kernel even though it uses pthread_mutex_lock and pthread_mutex_unlock. Why?

  6. (Advanced) Locking mechanisms can be strong or weak. A strong locking mechanism always resumes locked threads in the order in which they blocked. A weak locking mechanism does not. Why is strong locking more expensive to implement?