在多线程程序中,有一种读写者的问题,即对某些资源的访问,存在两种可能的情况,一种是访问必须排他的,称为写操作;另外一种访问是可共享的,称为读操作。

    处理读写着问题的两种常见策略是:强读者同步和强写者同步。在强读者同步过程中,总是给读者优先权,只要写着当前没有进行写操作,读者就可以获得访问权。在强写者同步过程中,通常将优先权先交给写者,而将读者延迟到所有等待的或者活动的写者都完成为止。简单的说:

    (1)可以同时存在多个读操作

    (2)写必须互斥(只允许一个写操作,不能读写操作同时进行)

    (3)写操作优先于读操作,(一旦有写操作,后续的读操作必须等待,唤醒时有限考虑写操作)

    下面是两种读写锁的使用示例.

    一:POSIX 下的rw_lock


点击(此处)折叠或打开

#include <pthread.h>

#include <cstdlib>

#include <ctime>

#include <iostream>

using namespace std;


static int count = 0;

class Test

{

private : 

    pthread_rwlock_t rwlock;

    

    static void* shared_task_handler(void* arg)

    {

        Test* testptr = static_cast<Test*>(arg);

        pthread_rwlock_rdlock(&testptr->rwlock);

        //    do the shared task here

        cout << "read---count = " << count << endl;

        if (pthread_rwlock_unlock(&testptr->rwlock) )

        {

            cout << "read unlock error " << endl;

        }

        return NULL;

    }

    

    static void * exclusive_task_handler(void * arg)

    {

        Test* testptr = static_cast<Test*>(arg);

        pthread_rwlock_wrlock(&testptr->rwlock);

        //do the exclusive task here

        ++count;

        cout << "write--count = " << count << endl;

        if (pthread_rwlock_unlock(&testptr->rwlock) )

        {

            cout << "write unlock error " << endl;

        }

        return NULL;

    }

    

public :

    typedef void* (*ThreadFunc) (void*);

    void start()

    {

        srand(time(NULL));

        

        if( pthread_rwlock_init(&rwlock,NULL) )

        {

            cout << "rwlock init error " << endl;

        }


        const int THREADS_NO = rand()%100;

        pthread_t* threads = new pthread_t[THREADS_NO];


        for(int i = 0; i < THREADS_NO; ++i)

        {

            ThreadFunc tmpfunc = rand() % 2 ? shared_task_handler : exclusive_task_handler;

            if (pthread_create(threads+i,NULL,tmpfunc,this))

            {

                cerr << "pthread_create fails" << endl;

                exit(1);

            }

        }

        rwlock

        for(int i=0; i<THREADS_NO; i++)

        {

            pthread_join(threads[i],NULL);

        }

        delete[] threads;

    }

};


int main()

{

    Test tmptest;

    tmptest.start();

}


output:

点击(此处)折叠或打开

lee@lee-desktop:~/share$ ./posix_read_write_lock

write--count = 1

write--count = 2

write--count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

write--count = 4

read---count = 4

write--count = 5

write--count = 6

read---count = 6

read---count = 6

read---count = 6

read---count = 6

write--count = 7

write--count = 8

read---count = 8

read---count = 8

write--count = 9

write--count = 10

read---count = 10

read---count = 10

read---count = 10

read---count = 10

read---count = 10

read---count = 10

read---count = 10

write--count = 11

write--count = 12

write--count = 13

write--count = 14

write--count = 15

read---count = 15


    二:利用pthread_cond_*  &  pthread_mutex_* 实现rw_lock


 

点击(此处)折叠或打开

#include <pthread.h>

#include <cstdlib>

#include <ctime>

#include <iostream>

using namespace std;


class RWLock 

{

private :

    pthread_mutex_t cnt_mutex;

    pthread_cond_t rw_cond;

    int rd_cnt, wr_cnt;


    RWLock(const RWLock&);

    RWLock& operator= (const RWLock&);


public :

    RWLock(): rd_cnt(0),wr_cnt(0)

    {

        pthread_mutex_init(&cnt_mutex, NULL);

        pthread_cond_init(&rw_cond, NULL);

    }


    void get_shared_lock()

    {

        pthread_mutex_lock(&cnt_mutex);

        while (wr_cnt >0)

        {

            pthread_cond_wait(&rw_cond,&cnt_mutex);

        }

        rd_cnt++;

        pthread_mutex_unlock(&cnt_mutex);

    }


    void release_shared_lock()

    {

        pthread_mutex_lock(&cnt_mutex);

        rd_cnt--;

        if (0 == rd_cnt)

        {

            pthread_cond_signal(&rw_cond);

        }

        pthread_mutex_unlock(&cnt_mutex);

    }


    void get_exclusive_lock()

    {

        pthread_mutex_lock(&cnt_mutex);

        while (rd_cnt + wr_cnt>0)

        {

            pthread_cond_wait(&rw_cond,&cnt_mutex);

        }

        wr_cnt++;

        pthread_mutex_unlock(&cnt_mutex);

    }


    void release_exclusive_lock()

    {

        pthread_mutex_lock(&cnt_mutex);

        wr_cnt--;

        pthread_cond_broadcast(&rw_cond);

        pthread_mutex_unlock(&cnt_mutex);

    }


    ~RWLock()

    {

        pthread_mutex_destroy(&cnt_mutex);

        pthread_cond_destroy(&rw_cond);

    }

};


static int count = 0;

class Test

{

private : 

    RWLock lock;

    

    static void* shared_task_handler(void* arg)

    {

        Test* testptr = static_cast<Test*>(arg);

        testptr->lock.get_shared_lock();

        //    do the shared task here

        cout << "read---count = " << count << endl;

        testptr->lock.release_shared_lock();

    }

    

    static void * exclusive_task_handler(void * arg)

    {

        Test* testptr = static_cast<Test*>(arg);

        testptr->lock.get_exclusive_lock();

        //do the exclusive task here

        ++count;

        cout << "write--count = " << count << endl;

        testptr->lock.release_exclusive_lock();

    }

    

public :

    typedef void* (*ThreadFunc) (void*);

    void start()

    {

        srand(time(NULL));


        const int THREADS_NO = rand()%100;

        pthread_t* threads = new pthread_t[THREADS_NO];


        for(int i = 0; i < THREADS_NO; ++i)

        {

            ThreadFunc tmpfunc = rand() % 2 ? shared_task_handler : exclusive_task_handler;

            if (pthread_create(threads+i,NULL,tmpfunc,this))

            {

                cerr << "pthread_create fails" << endl;

                exit(1);

            }

        }


        for(int i=0; i<THREADS_NO; i++)

        {

            pthread_join(threads[i],NULL);

        }


        delete[] threads;

    }

};


int main()

{

    Test tmptest;

    tmptest.start();

}


  output:

点击(此处)折叠或打开

lee@lee-desktop:~/share$ ./read_write_lock

read---count = 0

read---count = 0

read---count = 0

write--count = 1

read---count = 1

read---count = 1

read---count = 1

read---count = 1

write--count = 2

write--count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

read---count = 3

write--count = 4

write--count = 5

write--count = 6

write--count = 7

write--count = 8

write--count = 9

write--count = 10

write--count = 11

read---count = 11

write--count = 12

write--count = 13

read---count = 13

read---count = 13

write--count = 14

write--count = 15

write--count = 16

write--count = 17

write--count = 18

write--count = 19

read---count = 19

write--count = 20

read---count = 20

write--count = 21

read---count = 21

write--count = 22

read---count = 22

read---count = 22

write--count = 23

read---count = 23

read---count = 23

read---count = 23

write--count = 24

read---count = 24

write--count = 25

write--count = 26

write--count = 27

write--count = 28

read---count = 28

read---count = 28

write--count = 29

write--count = 30

read---count = 30

read---count = 30

read---count = 30

write--count = 31

read---count = 31

read---count = 31

write--count = 32

read---count = 32

write--count = 33

read---count = 33

read---count = 33

read---count = 33

read---count = 33

read---count = 33

write--count = 34

write--count = 35