电商网站建设 问题 心得体会,百度搜索引擎网址,选择扬中网站建设,网站框架设计图1.背景概念 在编写多线程的时候#xff0c;有一种情况是十分常见的。那就是#xff0c;有些公共数据修改的机会比较少。相比较改写#xff0c;它们读的机会反而高的多。这样就衍生出了读者写者模型#xff0c;在这个模型中#xff0c;有两类线程#xff1a;读者和写者。读…1.背景概念 在编写多线程的时候有一种情况是十分常见的。那就是有些公共数据修改的机会比较少。相比较改写它们读的机会反而高的多。这样就衍生出了读者写者模型在这个模型中有两类线程读者和写者。读者线程读取共享资源而写者线程则修改共享资源读者和读者之间为共享关系写者和写者为同步互斥关系读者和写者之间为互斥关系。 该模型有两种策略 读者优先策略 在读者优先策略中允许多个读者同时访问共享资源有读者在读时写者必须等待直到所有当前的读者和写者都完成访问。这种策略可以提高并发度但可能导致写者饥饿。 写者优先策略 在写者优先策略中一旦有写者等待新的读者必须等待直到所有当前的读者和写者都完成访问。这种策略可以减少写者的等待时间但可能导致读者饥饿。 通常而言在读的过程中往往伴随着查找的操作中间耗时很长。给这种代码段加锁会极大地降低我们程序的效率。那么有没有一种方法可以专门处理这种多读少写的情况呢 在Linux系统中可以使用信号量Semaphore或读写锁Read-Write Lock来解决读者写者问题。信号量可以用来实现互斥访问而读写锁则可以允许多个读者同时访问但在有写者等待时新的读者必须等待接下来我们介绍读写锁。 2.读写锁
读模式共享模式 多个线程可以同时以读模式持有读写锁。当一个线程以读模式获取到读写锁后其他线程如果也想要以读模式获取该锁是可以成功获取的。这是因为多个读操作通常不会相互干扰不会破坏数据的一致性。例如多个线程同时读取一个共享文件的内容它们可以同时进行不会有冲突。写模式独占模式 只有一个线程可以以写模式持有读写锁。当一个线程以写模式获取到读写锁时其他任何线程无论是想要以读模式还是写模式获取该锁都必须等待。这是因为写操作会修改共享资源如果有其他线程同时进行读或写操作可能会导致数据不一致。例如当一个线程正在修改一个共享文件时不允许其他线程同时读取或修改该文件。
在Linux中读写锁的类型为 pthread_rwlock_t其使用方法与互斥锁基本一致。
读写锁的创建
1. 可以使用PTHREAD_RWLOCK_INITIALIZER初始化创建全局的读写锁并且无需销毁。
pthread_rwlock_t rwlock PTHREAD_RWLOCK_INITIALIZER;2. 使用 pthread_rwlock_init 函数初始化读写锁。 int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr); 参数 rwlock指向要初始化的读写锁对象的指针。attr指向读写锁属性对象的指针如果不需要特殊属性可以设置为 NULL使用默认属性。 函数成功时返回 0失败时返回错误码。 加锁 int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); pthread_rwlock_rdlock 用于给读写锁申请一个读锁。如果读写锁当前没有被写锁占用那么调用线程可以立即获得读锁。如果读写锁当前被写锁占用那么调用线程将被阻塞直到写锁被释放。 int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); pthread_rwlock_wrlock 用于给读写锁申请一个写锁。如果读写锁当前没有被任何锁占用那么调用线程可以立即获得写锁。如果读写锁当前被读锁或写锁占用那么调用线程将被阻塞直到所有的读锁和写锁都被释放。 rwlock指向要申请读锁的读写锁对象的指针。 解锁 int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); pthread_rwlock_unlock 函数用于释放之前通过 pthread_rwlock_rdlock读锁或者 pthread_rwlock_wrlock写锁获取的读写锁。 读写锁的销毁 int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); 3.基于读写锁实现的读者写者模型 基于读写锁我们来实现一个测试代码看看效果 #include iostream
#include pthread.h
#include string
#include unistd.h
using namespace std;
int g_tickets 100;
pthread_rwlock_t rwlock PTHREAD_RWLOCK_INITIALIZER; // 读写锁
struct ThreadData
{pthread_t tid;string name;
};
void *ReaderRoutinue(void *arg)
{ThreadData *reader static_castThreadData *(arg);while (true){usleep(1000);pthread_rwlock_rdlock(rwlock); // 读锁if (g_tickets 0)cout reader-name check a ticket- g_tickets endl;else{pthread_rwlock_unlock(rwlock);break;}pthread_rwlock_unlock(rwlock);}return nullptr;
}
void *WriterRoutinue(void *arg)
{ThreadData *writer static_castThreadData *(arg);while (true){usleep(2000);pthread_rwlock_wrlock(rwlock); // 写锁if (g_tickets 0)cout writer-name get a ticket- g_tickets-- endl;else{pthread_rwlock_unlock(rwlock);break;}pthread_rwlock_unlock(rwlock);}return nullptr;
}
int main()
{ThreadData readers[5];ThreadData writers[2];for (int i 0; i 5; i){readers[i].name Reader- to_string(i 1);pthread_create(readers[i].tid, nullptr, ReaderRoutinue, readers[i]);}for (int i 0; i 2; i){writers[i].name Writer- to_string(i 1);pthread_create(writers[i].tid, nullptr, WriterRoutinue, writers[i]);}for (int i 0; i 5; i)pthread_join(readers[i].tid, nullptr);for (int i 0; i 2; i)pthread_join(writers[i].tid, nullptr);return 0;
}