This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

Lab 08 - Threading Part 2

Trylock Example

Previously we covered pthread_mutex_lock and pthread_mutex_unlock. There is also a third locking mechanism: pthread_mutex_trylock. Try lock will not wait until the lock is available, it will return immediately. It will return zero if it acquired the lock, else something else if not (specifically an error code, most commonly a number meaning “Lock is busy”).

Exercise 1: Modify the code from last week to use pthread_mutex_trylock instead of pthread_mutex_lock. Use a pair of threads, which will safely modify a global variable. The program will then join them, print the global variable, and close.

Producer-Consumer Model

Threads are obviously used where we want multiple things to happen at the same time. Therefore they are commonly employed for slow processes like in the following schemes:

  • 1 thread doing heavy calculation, 1 thread can interact with the user - threading means the program remains responsive to user input
  • 5 threads reading a file each, correcting spelling errors, and then saving the result - threading means all 5 can be done at the same time, rather than one after the other
  • 15 producer threads reading reading data and placing it in buffers, and 3 consumer threads reading these buffers and doing something with it - threading means that we can have many producers ensuring the buffers are always full for the consumers, the consumers can easily check many buffers and have the data ready for them when they need it

The final layout is called a producer-consumer model. It can interact with many buffers in the following way:

if(pthread_mutex_trylock(&lockA) == 0)
    //lock was available, modify the data here
else if(pthread_mutex_trylock(&lockB) == 0)
    //else, try store the data in another buffer

But is this a good idea? Hint: What happens if no locks are available? Think about how we can solve this.

Exercise 2: Create 3 threads which will generate a random number every second. The threads will loop forever. These will be our producers. They will safely put the random number into one of two buffers.

There will then be two other threads, our consumers, which will check if there is data in the buffers, and if so, print it.

Extension Tasks

  • Create a global variable that all threads will check regularly. If it is set to a specific value (called a sentinel), the threads will close. The main thread can then wait for the user to press enter (scanf) before closing. When it closes, it will set the global variable to the sentinel so each thread will exit, join them all, and then return zero.
  • Consider coding in such a way that we can easily change the number of producers/buffers/consumers with a single variable (each).

ie. int nProducerThreads = 15;

courses/be5b99cpl/labs/lab10.txt · Last modified: 2022/11/30 04:04 by brouggeo