什么网站可以做宣传,西安网站建设聚星互联,上海网站建筑公司,南京 网站建设有限公司一、概念 一把读写锁具备三种状态#xff1a; 读模式下加锁状态(读锁#xff09;写模式下加锁转态(写锁)不加锁状态2. 读写锁特性#xff1a; 读写锁是写模式加锁时#xff0c;解锁前#xff0c;所有对该锁加锁的线程都会阻塞。读写锁是读模式加锁时#xff0c;如果线程以…一、概念 一把读写锁具备三种状态 读模式下加锁状态(读锁写模式下加锁转态(写锁)不加锁状态2. 读写锁特性 读写锁是写模式加锁时解锁前所有对该锁加锁的线程都会阻塞。读写锁是读模式加锁时如果线程以读模式加锁会成功如果线程以写模式加锁会阻塞读写锁是读模式加锁时既有试图以写模式加锁的线程也有试图以读模式加锁的线程那么读模式会读阻塞随后的读模式锁请求优先满足写模式锁读锁、写锁并行阻塞写锁优先级高。读写锁也叫共享_独占锁当读写锁以读模式锁住时它以共享模式锁住当它以写模式锁住时它是独占锁住的写独占读共享。 3. 读写锁的特性: 线程A加读锁成功, 又来了三个线程, 做读操作, 可以加锁成功 读共享 - 并行处理线程A加写锁成功, 又来了三个线程, 做读操作, 三个线程阻塞 写独占线程A加读锁成功, 又来了B线程加写锁阻塞, 又来了C线程加读锁阻塞 读写不能同时写的优先级高4. 读写锁场景: 线程A加写锁成功, 线程B请求读锁 线程B阻塞线程A持有读锁, 线程B请求写锁 线程B阻塞线程A拥有读锁, 线程B请求读锁 线程B加锁成功线程A持有读锁, 然后线程B请求写锁, 然后线程C请求读锁 B阻塞c阻塞 - 写的优先级高A解锁B线程加写锁成功C继续阻塞B解锁C加读锁成功线程A持有写锁, 然后线程B请求读锁, 然后线程C请求写锁 BC阻塞A解锁C加写锁成功B继续阻塞C解锁B加读锁成功二、主要函数
1. 函数原型
#include pthread.h
pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); 初始化读写锁
pthread_rwlock_destroy(pthread_rwlock_t *rwlock); 销毁读写锁
2. 函数原型阻塞版本
#include pthread.h
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); 读锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); 写锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); 解锁 三、程序清单
1. 测试代码
#include stdio.h
#include unistd.h
#include pthread.hint counter; //全局资源
pthread_rwlock_t rwlock;void *th_write(void *arg)
{int t;int i (int)arg;while (1) {t counter;usleep(1000);pthread_rwlock_wrlock(rwlock);printf(write %d: %lu: counter %d counter %d\n, i, pthread_self(), t, counter);pthread_rwlock_unlock(rwlock);usleep(5000);}return NULL;
}void *th_read(void *arg)
{int t;int i (int)arg;while (1) {pthread_rwlock_rdlock(rwlock);printf(---------------read %d: %lu: %d\n, i, pthread_self(), counter);pthread_rwlock_unlock(rwlock);usleep(900);}return NULL;
}int main()
{int i;pthread_t tid[8];pthread_rwlock_init(rwlock, NULL);for (i 0; i 3; i)pthread_create(tid[i], NULL, th_write, (void*)i);for (i 0; i 5; i)pthread_create(tid[i 3], NULL, th_read, (void*)i);for (i 0; i 8; i)pthread_join(tid[i], NULL);pthread_rwlock_destroy(rwlock);return 0;
}输出结果 互斥锁实现读写锁
#includepthread.hpthread_mutex_t rdLock PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t wrLock PTHREAD_MUTEX_INITIALIZER;
int readCnt 0;//设置读锁调用次数的标志位//实现读锁共享锁
void rdLock()
{pthread_mutex_lock(rdLock);readCnt;if (readCnt 1)//有人读于是阻塞写锁pthread_mutex_lock(wrLock);pthread_mutex_unlock(rdLock);
}void rdUnlock()
{pthread_mutex_lock(rdLock);readCnt--;if (readCnt 0)//表示已没有人在读释放写锁可以写入了pthread_mutex_unlock(wrLock);pthread_mutex_unlock(rdLock);
}void wrLock()
{pthread_mutex_lock(wrLcok);
}void wrUnlock()
{pthread_mutex_unlock(wrLock);
}一、实验项目
【问题描述】程序 trainticket 中有 100 个线程其中 90 个线程是查余票数量的只有 10 个线程抢票每个线程一次买 10 张票。初始状态下一共有 1000 张票。因此执行完毕后还会剩下 900 张票。
程序 trainticket 在运行的时候需要传入参数即
参数 0表示不加任何锁参数 1表示使用读写锁参数 2表示使用互斥量
#include unistd.h
#include stdio.h
#include stdlib.h
#include string.h
#include pthread.hstruct Ticket
{int remain; // 余票数初始化为 1000pthread_rwlock_t rwlock; // 读写锁pthread_mutex_t mlock; // 互斥锁主要是为了和读写锁进行对比
}ticket;// 通过命令行传参数来取得这个值用来控制到底使用哪一种锁
// 0不加锁 1加读写锁 2加互斥锁
int lock 0;void* query(void* arg) //查票线程
{int name (int)arg;sleep(rand() % 5 1);if (lock 1)pthread_rwlock_rdlock(ticket.rwlock); // 读模式加锁else if (lock 2)pthread_mutex_lock(ticket.mlock);int remain ticket.remain;sleep(1);printf(%03d query: %d\n, name, remain);if (lock 1)pthread_rwlock_unlock(ticket.rwlock);else if (lock 2)pthread_mutex_unlock(ticket.mlock);return NULL;
}void* buy(void* arg) // 抢票线程
{int name (int)arg;if (lock 1)pthread_rwlock_wrlock(ticket.rwlock); // 写模式加锁else if (lock 2)pthread_mutex_lock(ticket.mlock);int remain ticket.remain;remain - 10; // 一次买 10 张票sleep(1);ticket.remain remain;printf(%03d buy 10 tickets\n, name);if (lock 1)pthread_rwlock_unlock(ticket.rwlock);else if (lock 2)pthread_mutex_unlock(ticket.mlock);sleep(rand() % 5 2);return NULL;
}int main(int argc, char* argv[])
{lock 0;if (argc 2) lock atoi(argv[1]);int names[100];pthread_t tid[100];int i;for (i 0; i 100; i) names[i] i;ticket.remain 1000;printf(remain ticket %d\n, ticket.remain);pthread_rwlock_init(ticket.rwlock, NULL);pthread_mutex_init(ticket.mlock, NULL);for (i 0; i 100; i) {if (i % 10 0)pthread_create(tid[i], NULL, buy, (void*)names[i]);elsepthread_create(tid[i], NULL, query, (void*)names[i]);}for (i 0; i 100; i) pthread_join(tid[i], NULL);pthread_rwlock_destroy(ticket.rwlock);pthread_mutex_destroy(ticket.mlock);printf(remain ticket %d\n, ticket.remain);return 0;
}