Step-by-step implementation of read-write locks

Source: Internet
Author: User
Tags semaphore

In multithreaded programming, shared variables need to be locked. However, frequent locking can have a significant effect on program efficiency. In some scenarios where read and write less, it is clearly not necessary for multiple threads to read data if they are mutually exclusive. So the read-write lock was born.

Lock rules for read and write locks:

1 If there is no write lock, then multiple threads can read the lock at the same time, and if there is a write lock, no read lock can be added.

2 No matter whether you add a read lock or a write lock, you cannot continue to write the lock.

Satisfying these two conditions, a read-write lock can be implemented initially. We use two locks, a variable, to implement a simple read-write lock, the code is as follows

Class Rwlock{public:rwlock (): read_cnt (0) {                pthread_mutex_init (&read_mtx,null);                Pthread_mutex_init (&write_mtx,null);} ~ Rwlock () {                Pthread_mutex_destroy (&READ_MTX);                Pthread_mutex_destroy (&WRITE_MTX);} void Readlock () {pthread_mutex_lock (&READ_MTX); if (++read_cnt = = 1) pthread_mutex_lock (&WRITE_MTX);p Thread_ Mutex_unlock (&READ_MTX);} void Readunlock () {pthread_mutex_lock (&READ_MTX); if (--read_cnt = = 0) pthread_mutex_unlock (&WRITE_MTX); Pthread_mutex_unlock (&READ_MTX);} void Writelock () {pthread_mutex_lock (&WRITE_MTX);} void Writeunlock () {pthread_mutex_unlock (&WRITE_MTX);} private:pthread_mutex_t read_mtx;pthread_mutex_t Write_mtx;int read_cnt; Number of Read locks};

First of all, when reading the lock, judge the number of readers, if it is 1, stating that he is the first reader, this time to add a write lock. If there is no writer, the lock succeeds. If there is a writer, then you need to wait for the write lock to release.

Second, the write lock, is the direct lock write_mtx, if there is no other reader or writer, lock success; otherwise wait for WRITE_MTX to be released.

This method of implementation is straightforward, but there is a problem. When the read-write lock is occupied by the reader, then the writer needs to wait for the read lock release, if another read the lock can be added lock success. This can lead to a hard-to-get write lock, and the read lock cannot be released. In practical applications, we do not expect this, as this may result in data not being updated in a timely manner and the data being read out of date. It is clear that the priority of the write lock should be higher than the read lock. So how do you implement such a read-write lock?

Then in the data structure of the read-write lock, two variables should be required to represent the number of readers and the writer who are waiting. The definition of a read-write lock is given first

Class Rwlock{public:    Rwlock ();    ~rwlock ();    void Readlock ();    void Writelock ();    void unlock ();    int Tryreadlock ();    int Trywritelock ();    Private:    pthread_mutex_t Rwmutex;    int refcount;   -1 indicates a writer, 0 means no lock, and a positive number indicates how many readers    int readwaiters;    int writewaiters;    pthread_cond_t Readcond;    pthread_cond_t Writecond;};

The implementation is as follows:

1. Constructor, responsible for initializing variables

Rwlock::rwlock () {    refcount     = 0;    Readwaiters  = 0;    writewaiters = 0;    Pthread_mutex_init (&rwmutex,null);    Pthread_cond_init (&readcond, NULL);    Pthread_cond_init (&writecond, NULL);}

2 destructors, destroying resources

Rwlock::~rwlock () {    refcount     = 0;    Readwaiters  = 0;    writewaiters = 0;    Pthread_mutex_destroy (&rwmutex);    Pthread_cond_destroy (&readcond);    Pthread_cond_destroy (&writecond);}

3 Plus read lock

void Rwlock::readlock () {    pthread_mutex_lock (&rwmutex);    while (RefCount < 0)    {        readwaiters++;        Pthread_cond_wait (&readcond,&rwmutex);        readwaiters--;    }    refcount++;    Pthread_mutex_unlock (&rwmutex);}

First of all, the Rwmutex lock, mainly for the reading area refcount variable. Then in the while loop, wait for the read semaphore. It is important to note that the while cannot be judged by the IF. We may think that when the readcond has a signal, the writer has already released the write lock, then refcount must be equal to 0, there is no need to use the while loop. Note, however, that pthread_cond_wait is the process of performing this function. First, it releases the lock Rwmutex, then waits for the readcond to have a signal, and then locks the Rwmutex when the semaphore is finally acquired. So there is a situation, after the Readcond get the signal, not enough time to lock Rwmutex, another thread at this time to obtain a write lock, it is clear that it can be obtained, RefCount became 1. If you do not judge RefCount, you will get an error.

4 Plus write lock

void Rwlock::writelock () {    pthread_mutex_lock (&rwmutex);    while (RefCount! = 0)    {        writewaiters++;        Pthread_cond_wait (&writecond,&rwmutex);        writewaiters--;    }    RefCount =-1;    Pthread_mutex_unlock (&rwmutex);}

Note points and read locks are all going to be a while loop, no longer repeating

5 Release Lock

void Rwlock::unlock () {    pthread_mutex_lock (&rwmutex);    if (RefCount = =-1)        refcount = 0;    else        refcount--;    if (RefCount = = 0)    {        if (writewaiters > 0)            pthread_cond_signal (&writecond);        else if (readwaiters > 0)            pthread_cond_broadcast (&readcond);    }    Pthread_mutex_unlock (&rwmutex);}

When unlocking, if recount==0, stating that no one has ever used a read-write lock, then first determine if there is a write lock wait, if so, the Writecond has a signal. If there is no writer, only the reader, then the Readcond signal volume broadcast.

Here, the function of the read-write lock is introduced. But notice that the locking interface above is blocked, and we will then introduce the non-blocking lock interface

6 non-blocking read lock

int Rwlock::tryreadlock () {    int ret = 0;    Pthread_mutex_lock (&rwmutex);    if (RefCount < 0 | | writewaiters > 0)    {        ret =-1;    }    else        refcount++;    Pthread_mutex_unlock (&rwmutex);    return ret;}

7 non-blocking write lock

int Rwlock::trywritelock () {    int ret = 0;    Pthread_mutex_lock (&rwmutex);    if (refcount! = 0)    {        ret =-1;    }    else        refcount =-1;    Pthread_mutex_unlock (&rwmutex);    return ret;}

The non-blocking interface is relatively simpler than the blocking interface, which is not repeated here.

Summary: This paper introduces the function of read-write lock and the implementation method in detail. Implementations are based on POSIX interfaces and are suitable for all UNIX-like systems. As for Windows systems, refer to this blog post

http://blog.csdn.net/querw/article/details/7214925

Step-by-step implementation of a read-write lock

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.