Applying C - Locking
Written by Harry Fairhead   
Tuesday, 27 May 2025
Article Index
Applying C - Locking
Mutex
Atomic

Using a mutex is very easy – getting it right can be more difficult. For example, in the previous case of updating a struct the problem is that the struct has to updated atomically. The solution is to make both updates subject to acquiring a lock.

That is:

pthread_mutex_t my_mutex=PTHREAD_MUTEX_INITIALIZER;
void * resetRec(void *p) {
    for ( j=1;;j++) {
       pthread_mutex_lock(&my_mutex);
        strcpy(me.name, "xxxxx");
        me.age = 0;
        pthread_mutex_unlock(&my_mutex);
    }
}

The main program does the same thing and locks the update to the struct:

int main(int argc, char** argv) {
    pthread_t pthread;
    int id = pthread_create(&pthread,NULL, 
resetRec, NULL); for (int i = 0;; i++) { pthread_mutex_lock(&my_mutex); strcpy(me.name, "Harry"); me.age = 18; pthread_mutex_unlock(&my_mutex); if (strcmp(me.name, "Harry") == 0 &&
me.age != 18) { printf("error %s %d %d", me.name, me.age,i); exit(0); } } return (EXIT_SUCCESS); }

If you try this out you will discover that it still doesn’t work. After a few thousand iterations the program will halt and print xxxxx, 0, 3456. We have stopped the problem of the two updates creating an invalid record, but we haven’t stopped the problem of the struct being changed by the thread during the if statement’s testing of its two fields, name and age. It can be very difficult to ensure that access to shared variables is fully protected. There is a tendency to think that we only have to lock when two threads are trying to perform the same or similar operation on a shared resource. In practice you need to lock whenever a thread accesses a shared resource.

To make it all work unlock in the main program has to be moved to after the if. This means that the amount of time that the mutex is unlocked by the main program is very small. Notice that the amount of time that the thread releases the lock is also very small and starvation of the second thread is now very likely.

There are some more advanced mutex features. For example, there is the:

pthread_mutex_trylock(&mymutex);

function which always returns at once, but with an error if the lock hasn’t been acquired. This can be used to allow a thread to get on with some work while it waits for the lock to come free. The default mutex is a fast mutex, which doesn’t check to see which thread locked it when attempting a lock. This means if the same thread tries to lock it a second time it is suspended and it is never able to unlock the mutex. Another type of mutex is a recursive mutex, which counts the number of times a thread has locked it and requires the same number of unlocks to free the mutex. There is also a separate rwlock that can be locked for reading only or for writing only.

In Chapter but not in this extract

  • Condition Variables
  • Scheduling
  • Deadline Scheduling

Summary

  • Multi-tasking is becoming increasingly common, even on small machines.

  • The original way of creating new processes is to use a fork which creates a new copy of the currently running process. Today it is more common to use threads, which are more efficient and closer bound than a fork.

  • Although C11 has a standard for threading, the original Pthreads library is still the most common way of implement threading.

  • Pthreads supports joinable and detached threads. A joinable thread can return a result to a thread that waits on its completion, whereas a detached thread cannot do this.

  • To avoid simultaneous access to resources you need to use locking. The mutex is one of the most basic locking devices.

  • A more complex locking device is the condition variable, which can be used to synchronize threads that can wait on the condition variable.

  • Threads and processes need to be scheduled by the operating system. Linux has a real time scheduling policy called FIFO, which is worth using, but the slightly less commonly used earliest deadline scheduling (EDS) is better.

Now available as a paperback or ebook from Amazon.

Applying C For The IoT With Linux

  1. C,IoT, POSIX & LINUX
  2. Kernel Mode, User Mode & Syscall
  3. Execution, Permissions & Systemd
    Extract Running Programs With Systemd
  4. Signals & Exceptions
    Extract  Signals
  5. Integer Arithmetic
    Extract: Basic Arithmetic As Bit Operations
    Extract: BCD Arithmetic 
  6. Fixed Point
    Extract: Simple Fixed Point Arithmetic
  7. Floating Point 
  8. File Descriptors
    Extract: Simple File Descriptors 
    Extract: Pipes 
  9. The Pseudo-File System
    Extract: The Pseudo File System
    Extract: Memory Mapped Files 
  10. Graphics
    Extract: framebuffer
  11. Sockets
    Extract: Sockets The Client
    Extract: Socket Server
  12. Threading
    Extract:  Pthreads
    Extract:  Locking ***NEW
    Extract:  Condition Variables
    Extract:  Deadline Scheduling
  13. Cores Atomics & Memory Management
    Extract: Applying C - Cores 
  14. Interupts & Polling
    Extract: Interrupts & Polling 
  15. Assembler
    Extract: Assembler

Also see the companion book: Fundamental C

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


Apache Syncope 4 Adds Live Sync
12/06/2025

Apache Syncope 4.0 Notturno has been released, with improvements including live sync,  OpenFGA integration, and a reworked persistence layer. Apache Syncope is an Open Source IAM (Identity A [ ... ]



Two Tools To Elevate Your MongoDB Experience
03/07/2025

The tools contradict each other; the first one allows you to write SQL instead of using Mongo's special syntax, while the other allows you to manipulate the database without having to write SQL a [ ... ]


More News

pico book

 

Comments




or email your comment to: comments@i-programmer.info



Last Updated ( Tuesday, 27 May 2025 )