Last Updated: 2021-04-18 Sun 21:38

CSCI 4061 Lab12: Thread / Mutex Basics

CODE DISTRIBUTION: lab12-code.zip

  • Download the code distribution
  • See further setup instructions below

CHANGELOG: Empty

1 Rationale

Threads are an analog to processes which share many similarities but differ in two important respects:

  • By default threads share their entire memory image while processes have distinct and separate memory images by default
  • Threads are usually coordinated via a Mutex (portmanteau of "mutual exclusion") while processes more often use Semaphores or File Lock

This lab introduces the basics of Posix Threads (PThreads) and shows how threads can be created and coordinated.

Grading Policy

Credit for this Lab is earned by completing the exercises here and submitting a Zip of the work to Gradescope. Students are responsible to check that the results produced locally via make test are reflected on Gradescope after submitting their completed Zip. Successful completion earns 1 Engagement Point.

Lab Exercises are open resource/open collaboration and students are encouraged to coopearte on labs. Students may submit work as groups of up to 5 to Gradescope: one person submits then adds the names of their group members to the submission.

See the full policies in the course syllabus.

2 Codepack

The codepack for this lab is linked at the top of this document. Always download it and unzip/unpack it. It should contain the following files which are briefly described.

File Use Description
QUESTIONS.txt EDIT Questions to answer: fill in the multiple choice selections in this file.
proc_v_thread.c Provided C file to examine / run to answer QUIZ questions
thread_messages.c EDIT C file to study and complete for the CODE portion. See instructions in QUESTIONS.txt
QUESTIONS.txt.bk Backup Backup copy of the original file to help revert if needed
Makefile Build Enables make test and make zip
testy Testing Test running scripts
test_lab12.org Testing Tests for this lab
test_quiz_filter Testing Used to simplify quiz checksum

3 QUESTIONS.txt File Contents

Below are the contents of the QUESTIONS.txt file for the lab. Follow the instructions in it to complete the QUIZ and CODE questions for the lab.

                           __________________

                            LAB 12 QUESTIONS
                           __________________





Lab Instructions
================

  Follow the instructions below to experiment with topics related to
  this lab.
  - For sections marked QUIZ, fill in an (X) for the appropriate
    response in this file. Use the command `make test-quiz' to see if
    all of your answers are correct.
  - For sections marked CODE, complete the code indicated. Use the
    command `make test-code' to check if your code is complete.
  - DO NOT CHANGE any parts of this file except the QUIZ sections as it
    may interfere with the tests otherwise.
  - If your `QUESTIONS.txt' file seems corrupted, restore it by copying
    over the `QUESTIONS.txt.bk' backup file.
  - When you complete the exercises, check your answers with `make test'
    and if all is well, create a zip file with `make zip' and upload it
    to Gradescope. Ensure that the Autograder there reflects your local
    results.
  - IF YOU WORK IN A GROUP only one member needs to submit and then add
    the names of their group.


QUIZ Threads basic usage in proc_v_thread.c
===========================================

  Examine the code in `proc_v_thread.c' and run it with its two
  variants:
  ,----
  | >> ./proc_v_thread proc
  | ...
  | >> ./proc_v_thread thread
  | ...
  `----
  Study the results and the code itself and answer the following
  questions.

  Which function is used to start a thread running?
  - ( ) pthread_start()
  - ( ) pthread_create()
  - ( ) pthread_fork()
  - ( ) fork()

  While a call to fork() will start a child process at the next line of
  code, starting a thread...
  - ( ) Also starts at the new thread at the next line of code
  - ( ) Starts the new thread back at the beginning of the main()
    function
  - ( ) Begins the thread in a function specified when the thread is
    started
  - ( ) Starts a new program image running much like exec() does

  The wait() / waitpid() system call for processes has the following
  equivalent for threads...
  - ( ) pthread_join()
  - ( ) wait_threadid()
  - ( ) pthread_wait()
  - ( ) pthread_exit()

  The obvious observable difference between running `./proc_v_thread
  proc' and `./proc_v_thread thread' is
  - ( ) The child process does not modify the parent process global
    variable while the thread does
  - ( ) The child process starts slower than the new thread so the
    thread version completes faster
  - ( ) The thread exec()'s a program and therefore never returns
    control to main() while the child process does not
  - ( ) It is not possible to coordinate the new thread with the main
    thread while the child process can be wait()'d for


CODE Complete thread_messages.c
===============================

  Compile and run the provided but incomplete `thread_messages.c'
  program. You should notice that the output appears incorrect: each
  thread is meant to place a message in a global array but due to a lack
  of coordination, this behavior is unreliable.
  ,----
  | > make thread_messages
  | gcc -Wall -Werror -g -Wno-format-truncation -c thread_messages.c
  | gcc -Wall -Werror -g -Wno-format-truncation -o thread_messages thread_messages.o -lpthread
  | 
  | > ./thread_messages 
  | usage: ./thread_messages <nthreads>
  | 
  | > ./thread_messages 4
  | nthreads:  4
  | msg_index: 4
  | msg_arr[0]: I'm a thread!
  | msg_arr[1]: (null)
  | msg_arr[2]: I'm a thread!
  | msg_arr[3]: (null)
  | 
  | > ./thread_messages 4
  | nthreads:  4
  | msg_index: 4
  | msg_arr[0]: I'm a thread!
  | msg_arr[1]: I'm a thread!
  | msg_arr[2]: I'm a thread!
  | msg_arr[3]: (null)
  | 
  | > ./thread_messages 6
  | nthreads:  6
  | msg_index: 6
  | msg_arr[0]: I'm a thread!
  | msg_arr[1]: I'm a thread!
  | msg_arr[2]: (null)
  | msg_arr[3]: (null)
  | msg_arr[4]: I'm a thread!
  | msg_arr[5]: I'm a thread!
  `----

  Research the use of a Mutex in the pthreads library. Its simple use
  case is similar to Semaphores but a Mutex is more closely aligned with
  coordinating threads. You will need to use the following
  types/functions to coordinate threads as they access the global array.
  - `pthread_mutex_t' type for mutexes
  - `pthread_mutex_init()'
  - `pthread_mutex_lock()'
  - `pthread_mutex_unlock()'

  Correct output will appear as
  ,----
  | > ./thread_messages 4
  | nthreads:  4
  | msg_index: 4
  | msg_arr[0]: I'm a thread!
  | msg_arr[1]: I'm a thread!
  | msg_arr[2]: I'm a thread!
  | msg_arr[3]: I'm a thread!
  | 
  | > ./thread_messages 6
  | nthreads:  6
  | msg_index: 6
  | msg_arr[0]: I'm a thread!
  | msg_arr[1]: I'm a thread!
  | msg_arr[2]: I'm a thread!
  | msg_arr[3]: I'm a thread!
  | msg_arr[4]: I'm a thread!
  | msg_arr[5]: I'm a thread!
  `----

  NOTE: the purpose of the exercise is to use a mutex to coordinate
  threads in a Critical Region. This problem can certainly be solved via
  means such as only running a single thread at a time but the point is
  get acquainted to using a mutex to control access to shared resource.

4 Submission

Follow the instructions at the end of Lab01 if you need a refresher on how to upload your completed lab zip to Gradescope.


Author: Chris Kauffman (kauffman@umn.edu)
Date: 2021-04-18 Sun 21:38