Analysis of Inter-thread communication 2: read/write locks and spin locks, analysis of spin

Source: Internet
Author: User

Analysis of Inter-thread communication 2: read/write locks and spin locks, analysis of spin

The mutex and condition variables are used for thread synchronization. This article discusses the use of read/write locks and spin locks, and provides the corresponding code and precautions, the relevant code can also be found in myGithub.

 Read/write lock

The mutex is either locked or unlocked, and only one thread can lock it at a time, the read/write locks differentiate the read data lock requests of the thread from the write data lock requests. In some cases, the program has a higher concurrency. For read/write locks, only one thread can occupy the read/write locks in the write mode at a time, but multiple threads can simultaneously occupy the read/write locks in the Read mode. Although the implementation of read/write locks varies, when the read/write locks are locked in Read mode, if another thread attempts to lock the lock in write mode, A read/write lock usually blocks subsequent read-mode requests. In this way, the Read mode lock is not used for a long time, and the waiting write mode lock requests are not satisfied. A read/write lock is also called a shared-exclusive lock ). The following is a read/write lock to solve the problem of the classic reader and writer. The Code is as follows:

#include <stdio.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#define MAXNTHREADS 100#define MIN(a,b) (((a) < (b))?(a):(b))void *reader(void *); void *writer(void *); int nloop = 1000, nreaders = 6, nwriters = 4;struct {  pthread_rwlock_t  rwlock;  pthread_mutex_t   rcountlock;  int               nreaders;  int               nwriters;} shared = { PTHREAD_RWLOCK_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };int main(int argc, char **argv){    int     c, i;    pthread_t   tid_readers[MAXNTHREADS], tid_writers[MAXNTHREADS];    while ( (c = getopt(argc, argv, "n:r:w:")) != -1) {        switch (c) {        case 'n':            nloop = atoi(optarg);            break;        case 'r':            nreaders = MIN(atoi(optarg),MAXNTHREADS);            break;        case 'w':            nwriters = MIN(atoi(optarg),MAXNTHREADS);            break;        }       }       if (optind != argc)    {           printf("usage: read_write_lock_example [-n #loops ] [ -r #readers ] [ -w #writers ]");        return 1;    }       /* create all the reader and writer threads */    for (i = 0; i < nreaders; i++)        pthread_create(&tid_readers[i], NULL, reader, NULL);    for (i = 0; i < nwriters; i++)        pthread_create(&tid_writers[i], NULL, writer, NULL);    /* wait for all the threads to complete */    for (i = 0; i < nreaders; i++)        pthread_join(tid_readers[i], NULL);    for (i = 0; i < nwriters; i++)        pthread_join(tid_writers[i], NULL);    exit(0);}void* reader(void *arg){    int     i;    for (i = 0; i < nloop; i++) {        pthread_rwlock_rdlock(&shared.rwlock);        pthread_mutex_lock(&shared.rcountlock);        shared.nreaders++;  /* shared by all readers; must protect */        pthread_mutex_unlock(&shared.rcountlock);        if (shared.nwriters > 0)        {            printf("reader: %d writers found", shared.nwriters);            return (void*)0;        }        pthread_mutex_lock(&shared.rcountlock);        shared.nreaders--;  /* shared by all readers; must protect */        pthread_mutex_unlock(&shared.rcountlock);        pthread_rwlock_unlock(&shared.rwlock);    }    return(NULL);}void* writer(void *arg){    int     i;    for (i = 0; i < nloop; i++) {        pthread_rwlock_wrlock(&shared.rwlock);        shared.nwriters++;  /* only one writer; need not protect */        if (shared.nwriters > 1)        {            printf("writer: %d writers found", shared.nwriters);            return (void*)0;        }        if (shared.nreaders > 0)        {            printf("writer: %d readers found", shared.nreaders);            return (void*)0;        }        shared.nwriters--;  /* only one writer; need not protect */        pthread_rwlock_unlock(&shared.rwlock);    }    return(NULL);}

The above program implements synchronization between the read thread and the write thread, which is worth noting in the following aspects:

I) In reader, modify shared. when the nreaders value is used (although pthread_rwlock_rdlock is used to add a read lock), the mutex volume needs to be locked because multiple threads can obtain the read lock and modify the value.

II) In writer, when modifying the value of shared. nwriters, no mutex lock is required because only one thread may obtain the write lock.

 Spin locks)

 The spin lock is similar to the mutex. When the lock thread that gets the mutex is blocked, the thread enters the sleep state, and the thread is in the busy-waiting state when obtaining the spin lock, that is, it will not let out the CPU, consume CPU resources, and repeatedly try to obtain the spin lock until it is obtained. The spin lock applies to the situation where the thread holds the spin lock for a relatively short period of time and the thread does not want to consume the re-scheduling cost. Spin locks can usually be efficiently implemented using the test-and-set command.

You can use pthread_spin_lock or phread_spin_trylock to obtain the spin lock, but note that the thread should not call any function that may bring the thread into sleep state during the spin lock, because if you do so, when other threads try to obtain this spin lock, the CPU resources will be consumed accordingly.

Many mutex implementations are very efficient. Even when the spin lock is used, the use of mutex has almost no impact on program performance. In fact, when the mutex gets a lock, if the current lock cannot be obtained, the thread does not sleep immediately, but waits for a while to see if it can be obtained (while the spin lock is always busy ), if it exceeds a certain period of time, the thread enters the sleep state. In addition, the context speed of the current processor switching thread is getting faster and faster, making the use of spin locks less and less. Whether mutex or spin lock is used is summarized as follows:

A. Mutex is suitable for scenarios with frequent lock operations and has better adaptability. Compared with spin lock, it will spend more time (mainly context switching), but it can be used in complex application scenarios in actual development, provide greater flexibility while ensuring certain performance.

B. The lock/unlock performance of spin lock is better (it takes less cpu instructions), but it is only applicable to scenarios with short running time in the critical section. In actual software development, unless programmers have a good understanding of the lock operation behavior of their programs, otherwise, it is not a good idea to use spin lock (usually a multi-threaded program has tens of thousands of lock operations, if the lock operation fails (contended lock requests) if the number is too large, it will waste a lot of time to wait ).

C. A more secure method may be to use Mutex first (conservatively). If there is further demand for performance, you can try to use spin lock for optimization. After all, our programs do not have as high performance requirements as Linux kernel does (the most common lock operations for Linux Kernel are spin lock and rw lock ).

References

Synchronization of 11.6 threads in advanced programming in UNIX environment
UNIX Network Programming Volume 2: inter-process communication chapter 7th, Chapter 8th and Chapter 10th
Http://www.parallellabs.com/2010/01/31/pthreads-programming-spin-lock-vs-mutex-performance-analysis/



Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.