Linux Multithreading Practice (6)--posix read-write lock solves reader writer's problem

Source: Internet
Author: User
Tags mutex posix

POSIX read-write lock

int Pthread_rwlock_init (pthread_rwlock_t *restrict rwlock,                        const pthread_rwlockattr_t *restrict attr); int pthread _rwlock_destroy (pthread_rwlock_t *rwlock); int Pthread_rwlock_rdlock (pthread_rwlock_t *rwlock); int Pthread_rwlock_ Wrlock (pthread_rwlock_t *rwlock); int Pthread_rwlock_unlock (pthread_rwlock_t *rwlock);

Read and write locks are similar to mutexes, but read-write locks allow for higher parallelism. Read-write locks are used for reading called shared locks, and read-write locks are used to write called exclusive locks;

Read-write lock rules:

As long as no thread holds a given read-write lock for writing, then any number of threads can hold read-write locks for reading;

A read-write lock can be allocated for write only if no thread holds a given read-write lock for reading or for writing;

POSIX spin lock
int Pthread_spin_destroy (pthread_spinlock_t *lock); int Pthread_spin_init (pthread_spinlock_t *lock, int pshared); int Pthread_spin_lock (pthread_spinlock_t *lock); int Pthread_spin_trylock (pthread_spinlock_t *lock); int Pthread_spin_ Unlock (pthread_spinlock_t *lock);

A spin lock is similar to a mutex, and its performance is higher than the mutex lock;

One of the important differences between a spin lock and a mutex is that the thread does not hang when the thread is requesting a spin lock, and it is always in a busy state (always spinning, the CPU is in wasting state);

spin locks can be used in situations where a lock is held for a short time, and the thread does not want to spend too much on rescheduling.

spin locks are often used as the underlying primitives to implement other types of locks: for example, some mutex implementations will spin for a short period of time when attempting to obtain a mutex, and only hibernate when the spin count reaches a certain threshold; Therefore, many mutex implementations are so hilarious that the performance of an application using mutexes is essentially the same as the performance of a spin lock.

Therefore, spin locks are only useful in certain situations, such as at the user level, where spin locks are not very useful unless they are run in a real-time scheduling class that does not allow preemption.

reader Writer's question

Problem description

A data object can be shared by multiple concurrent processes. Some of these processes may only need to read the contents of the shared object, while other processes may want to update the contents of the shared object.

Reader: Only interested in the process of reading;

written by: Other processes (write only, or read and write);

Rules

allows multiple readers to read data at the same time;

There is only one writer who can write the data;

The writer is unable to read while writing, and vice versa.

/** Implementation 1: Using read-write locks to solve the "reader-writer problem" thinking: the need to read and write a file implemented as a string; Reader process: You can read the string all at once, and then print read the writer process: only one character at a time (the character is written from A~z), and the write information is printed after modification. **///read-write lock pthread_rwlock_t rwlock;const unsigned readercount = 2; Number of Readers const unsigned writerconut = 5;       Writer number const int PAPERSIZE = 32;        File length char paper[papersize+1]; File unsigned short int write_index = 0;  The writer needs to write the position of char ch = ' A ';  The writer needs to write the letter pthread_t Thread[readercount+writerconut];    Reader + writer thread//reader thread void *reader (void *args) {int number = * (int *) args;    Delete (int *) args;        while (true) {//Get shared lock Pthread_rwlock_rdlock (&rwlock);        Start reading printf ("# # Reader%d was reading...\n", number);        printf ("Text:%s\n", paper);        printf ("Reader%d end reading...\n", number);        Unlock shared lock Pthread_rwlock_unlock (&rwlock);    Sleep (1); } pthread_exit (NULL);}    Writer thread void *writer (void *args) {int number = * (int *) args;    Delete (int *) args; while (true) {//Get write lock Pthread_rwlock_wrlock(&rwlock);        Start writing printf ("+ + writer%d was writing...\n", number);        Paper[write_index] = ch;        Write_index = (write_index+1)%papersize;        ch = ch+1;        if (ch > ' Z ') ch = ' A ';        printf ("Writer%d End writing...\n", number);        Release write lock Pthread_rwlock_unlock (&rwlock);    Sleep (1); } pthread_exit (NULL);}    int main () {memset (paper, 0, sizeof (paper));    Pthread_rwlock_init (&rwlock, NULL);    for (unsigned int i = 0; i < Readercount; ++i) pthread_create (&thread[i], NULL, reader, new Int (i)); for (unsigned int i = 0; i < writerconut; ++i) pthread_create (&thread[readercount+i], NULL, writer, new Int (    i));    for (unsigned int i = 0; i < readercount+writerconut; ++i) Pthread_join (Thread[i], NULL); Pthread_rwlock_destroy (&rwlock);}

/** Implementation 2: Use the POSIX semaphore to solve the problem of reader-writer by using the "reader-first" strategy: if the new reader to: ① no reader, writer, the new reader can read, ② the writer waits, but other readers are reading, the new reader can also read, ③ write, new readers wait. If the new writer to: ① no reader, the new writer can write, ② have readers, new writer waiting, ③ have other writer, new writer waiting. **///need two mutex to implement pthread_mutex_t rmutex;pthread_mutex_t wmutex;const unsigned readercount = 5; Number of Readers const unsigned writerconut = 5;       Writer number const int PAPERSIZE = 32;        File length char paper[papersize+1]; File unsigned short int write_index = 0;  The writer needs to write the position of char ch = ' A ';  The writer needs to write the letter pthread_t Thread[readercount+writerconut];    Reader + writer thread int nreader = 0;//reader thread void *reader (void *args) {int number = * (int *) args;    Delete (int *) args;        while (true) {Pthread_mutex_lock (&rmutex);        If it is the first reader, lock the Wmutex if (Nreader = = 0) pthread_mutex_lock (&wmutex);        + + Nreader;        Pthread_mutex_unlock (&rmutex);        Start reading printf ("# # Reader%d was reading...\n", number);        printf ("Text:%s\n", paper);        printf ("Reader%d end reading...\n\n", number); Pthread_mutex_lock (&rmutex);        --Nreader;        If it is the last reader, unlock wmutex if (Nreader = = 0) pthread_mutex_unlock (&wmutex);        Pthread_mutex_unlock (&rmutex);    Sleep (1); } pthread_exit (NULL);}    Writer thread void *writer (void *args) {int number = * (int *) args;    Delete (int *) args;        while (true) {//Get write lock Pthread_mutex_lock (&wmutex);        Start writing printf ("+ + writer%d was writing...\n", number);        Paper[write_index] = ch;        Write_index = (write_index+1)%papersize;        ch = ch+1;        if (ch > ' Z ') ch = ' A ';        printf ("Writer%d End writing...\n\n", number);        Release write lock Pthread_mutex_unlock (&wmutex);    Sleep (1); } pthread_exit (NULL);}    int main () {memset (paper, 0, sizeof (paper));    Pthread_mutex_init (&rmutex, NULL);    Pthread_mutex_init (&wmutex, NULL); for (unsigned int i = 0; i < Readercount; ++i) pthread_create (&thread[i], NULL, reader, new int (i)); for (unsigned int i = 0; i < writerconut; ++i) pthread_create (&thread[readercount+i], NULL, writer, new Int (    i));    for (unsigned int i = 0; i < readercount+writerconut; ++i) Pthread_join (Thread[i], NULL);    Pthread_mutex_destroy (&rmutex); Pthread_mutex_destroy (&wmutex);}

Summary of the thought of "reader first": Reader's first design idea is that the reading process can continue to read as long as there are other read processes reading, and the write process must wait for all read processes to be unreadable before writing, even if the write process may have filed earlier than some read processes. The algorithm allows subsequent readers to come in as long as there is a reader active, and the result of this strategy is that if there is a steady flow of readers, then these readers will be allowed to enter upon arrival. And the writer is always suspended until there is no reader.

Linux Multithreading Practice (6)--posix read-write lock solves reader writer's problem

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.