当前位置: 首页 > news >正文

怎样建设学校网站济南seo关键词排名工具

怎样建设学校网站,济南seo关键词排名工具,最出名的网站建设公司,ppt简洁模板整套免费Linux读写锁的容易犯的问题 读写锁是互斥锁之外的另一种用于多线程之间同步的一种方式。 多线程对于一个共享变量的读操作是安全的#xff0c; 而写操作是不安全的。如果在一个读很多而写很少的场景之下#xff0c;那么使用互斥锁将会阻碍大量的线程安全的读操作的进行。在…Linux读写锁的容易犯的问题 读写锁是互斥锁之外的另一种用于多线程之间同步的一种方式。 多线程对于一个共享变量的读操作是安全的 而写操作是不安全的。如果在一个读很多而写很少的场景之下那么使用互斥锁将会阻碍大量的线程安全的读操作的进行。在这种场景下读写锁这样一种设计便诞生了。 读写锁的特性如下表所示 总结起来就是读读不互斥 读写互斥 写写互斥。 读写读不互斥互斥写互斥互斥 看似这样好的一个设计在实际的使用中确存在诸多的使用误区陈硕大神在他的Linux多线程服务端编程一书中曾给出他的建议不要使用读写锁。 为什么如此呢 下面一一道来。 读写锁使用的正确性 读写锁第一个容易出错的地方就是可能在持有读锁的地方修改了共享数据。对于一些比较简单的方法可能是不容易出错的但是对于嵌套调用的场景下也是容易犯错的。例如下面的例子read方法持有了读锁但是operator4会修改共享变量。由于operator4的调用深度较深因此可能容易犯错。 //operator4会修改共享变量 void operation4(); {//... }void operation3() {operation4(); }void operation2() {operation3(); }void read() {std::shared_lockstd::shared_mutex lock(mtx);operation1(); }读写锁性能上的开销 读写锁从设计上看是比互斥锁要复杂一些因此其内部加锁和解锁的逻辑也要比互斥锁要复杂。 下面是glibc读写锁的数据结构可以推测在加锁解锁过程中要更新reader和writers的数目而互斥锁是无需这样的操作的。 struct __pthread_rwlock_arch_t {unsigned int __readers;unsigned int __writers;unsigned int __wrphase_futex;unsigned int __writers_futex;unsigned int __pad3;unsigned int __pad4;int __cur_writer;int __shared;unsigned long int __pad1;unsigned long int __pad2;/* FLAGS must stay at this position in the structure to maintainbinary compatibility. */unsigned int __flags; };下面的一个例子使用互斥锁和读写锁分别对一个临界区进行反复的加锁和解锁。因为临界区没有内容因此开销基本都在锁的加锁和解锁上。 //g test1.cpp -o test1 #include pthread.h #include iostream #include unistd.hpthread_mutex_t mutex; int i 0;void *thread_func(void* args) {int j;for(j0; j10000000; j) {pthread_mutex_lock(mutex);// testpthread_mutex_unlock(mutex);}pthread_exit((void *)0); }int main(void) {pthread_t id1;pthread_t id2;pthread_t id3;pthread_t id4;pthread_mutex_init(mutex, NULL);pthread_create(id1, NULL, thread_func, (void *)0);pthread_create(id2, NULL, thread_func, (void *)0);pthread_create(id3, NULL, thread_func, (void *)0);pthread_create(id4, NULL, thread_func, (void *)0);pthread_join(id1, NULL);pthread_join(id2, NULL);pthread_join(id3, NULL);pthread_join(id4, NULL);pthread_mutex_destroy(mutex); }//g test2.cpp -o test2 #include pthread.h #include iostream #include unistd.hpthread_rwlock_t rwlock; int i 0;void *thread_func(void* args) {int j;for(j0; j10000000; j) {pthread_rwlock_rdlock(rwlock);//test2pthread_rwlock_unlock(rwlock);}pthread_exit((void *)0); }int main(void) {pthread_t id1;pthread_t id2;pthread_t id3;pthread_t id4;pthread_rwlock_init(rwlock, NULL);pthread_create(id1, NULL, thread_func, (void *)0);pthread_create(id2, NULL, thread_func, (void *)0);pthread_create(id3, NULL, thread_func, (void *)0);pthread_create(id4, NULL, thread_func, (void *)0);pthread_join(id1, NULL);pthread_join(id2, NULL);pthread_join(id3, NULL);pthread_join(id4, NULL);pthread_rwlock_destroy(rwlock); }[rootlocalhost test1]# time ./test1real 0m2.531s user 0m5.175s sys 0m4.200s [rootlocalhost test1]# time ./test2real 0m4.490s user 0m17.626s sys 0m0.004s可以看出单纯从加锁和解锁的角度看互斥锁的性能要好于读写锁。 当然这里测试时临界区的内容时空的如果临界区较大那么读写锁的性能可能会优于互斥锁。 不过在多线程编程中我们总是会尽可能的减少临界区的大小因此很多时候读写锁并没有想象中的那么高效。 读写锁容易造成死锁 前面提到过读写锁这样的设计就是在读多写少的场景下产生的然而这样的场景下很容易造成写操作的饥饿。因为读操作过多写操作不能拿到锁造成写操作的阻塞。 因此写操作获取锁通常拥有高优先级。 这样的设定对于下面的场景将会造成死锁。假设有线程A、B和锁按如下时序执行 1、线程A申请读锁2、线程B申请写锁3、线程A再次申请读锁 第2步中线程B在申请写锁的时候线程A还没有释放读锁于是需要等待。第3步中因此线程B正在申请写锁于是线程A申请读锁将会被阻塞于是陷入了死锁的状态。 下面使用c17的shared_mutex来模拟这样的场景。 #include iostream #include thread #include mutex #include condition_variable #include shared_mutexvoid print() {std::cout \n; } templatetypename T, typename... Args void print(T first, Args ...args) {std::cout first ;print(std::forwardArgs(args)...); }std::shared_mutex mtx; int step 0; std::mutex cond_mtx; std::condition_variable cond;void read() {//step0: 读锁std::shared_lockstd::shared_mutex lock(mtx);std::unique_lockstd::mutex uniqueLock(cond_mtx);print(read lock 1);//通知step0结束step;cond.notify_all();//等待step1: 写锁 结束cond.wait(uniqueLock, []{return step 2;});uniqueLock.unlock();//step2: 再次读锁std::shared_lockstd::shared_mutex lock1(mtx);print(read lock 2); }void write() {//等待step0: 读锁 结束std::unique_lockstd::mutex uniqueLock(cond_mtx);cond.wait(uniqueLock, []{return step 1;});uniqueLock.unlock();//step1: 写锁std::lock_guardstd::shared_mutex lock(mtx);uniqueLock.lock();print(write lock);//通知step1结束step;cond.notify_all();uniqueLock.unlock(); }int main() {std::thread t_read{read};std::thread t_write{write};t_read.join();t_write.join();return 0; }可以使用下面的在线版本进行测试。 have a try 在线版本的输出是下面这样的程序由于死锁执行超时被杀掉了。 Killed - processing time exceeded Program terminated with signal: SIGKILL死锁的原因就是线程1与线程2相互等待导致。 对于glibc的读写锁其提供了读优先和写优先的属性。 使用pthread_rwlockattr_setkind_np方法即可设置读写锁的属性。其拥有下面的属性 PTHREAD_RWLOCK_PREFER_READER_NP, //读者优先即同时请求读锁和写锁时请求读锁的线程优先获得锁PTHREAD_RWLOCK_PREFER_WRITER_NP, //不要被名字所迷惑也是读者优先PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, //写者优先即同时请求读锁和写锁时请求写锁的线程优先获得锁PTHREAD_RWLOCK_DEFAULT_NP PTHREAD_RWLOCK_PREFER_READER_NP // 默认读者优先 glibc的读写锁模式是读优先的。下面分别使用读优先和写优先来进行测试。 写优先 #include iostream #include pthread.h #include unistd.hpthread_rwlock_t m_lock; pthread_rwlockattr_t attr;int A 0, B 0;// thread1 void* threadFunc1(void* p) {printf(thread 1 running..\n);pthread_rwlock_rdlock(m_lock);printf(thread 1 read source A%d\n, A);usleep(3000000); // 等待3s此时线程2大概率会被唤醒并申请写锁pthread_rwlock_rdlock(m_lock);printf(thread 1 read source B%d\n, B);//释放读锁pthread_rwlock_unlock(m_lock);pthread_rwlock_unlock(m_lock);return NULL; }//thread2 void* threadFunc2(void* p) {printf(thread 2 running..\n);pthread_rwlock_wrlock(m_lock);A 1;B 1;printf(thread 2 write source A and B\n);//释放写锁pthread_rwlock_unlock(m_lock);return NULL; }int main() {pthread_rwlockattr_init(attr);pthread_rwlockattr_setkind_np(attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);//设置写锁优先级高//初始化读写锁if (pthread_rwlock_init(m_lock, attr) ! 0){printf(init rwlock failed\n);return -1;}//初始化线程pthread_t hThread1;pthread_t hThread2;if (pthread_create(hThread1, NULL, threadFunc1, NULL) ! 0){printf(create thread 1 failed\n);return -1;}usleep(1000000);if (pthread_create(hThread2, NULL, threadFunc2, NULL) ! 0){printf(create thread 2 failed\n);return -1;}pthread_join(hThread1, NULL);pthread_join(hThread2, NULL);pthread_rwlock_destroy(m_lock);return 0; }设置写优先会导致死锁。 读优先 #include iostream #include pthread.h #include unistd.hpthread_rwlock_t m_lock; pthread_rwlockattr_t attr;int A 0, B 0;// thread1 void* threadFunc1(void* p) {printf(thread 1 running..\n);pthread_rwlock_rdlock(m_lock);printf(thread 1 read source A%d\n, A);usleep(3000000); // 等待3s此时线程2大概率会被唤醒并申请写锁pthread_rwlock_rdlock(m_lock);printf(thread 1 read source B%d\n, B);//释放读锁pthread_rwlock_unlock(m_lock);pthread_rwlock_unlock(m_lock);return NULL; }//thread2 void* threadFunc2(void* p) {printf(thread 2 running..\n);pthread_rwlock_wrlock(m_lock);A 1;B 1;printf(thread 2 write source A and B\n);//释放写锁pthread_rwlock_unlock(m_lock);return NULL; }int main() {pthread_rwlockattr_init(attr);pthread_rwlockattr_setkind_np(attr, PTHREAD_RWLOCK_PREFER_READER_NP);//初始化读写锁if (pthread_rwlock_init(m_lock, attr) ! 0){printf(init rwlock failed\n);return -1;}//初始化线程pthread_t hThread1;pthread_t hThread2;if (pthread_create(hThread1, NULL, threadFunc1, NULL) ! 0){printf(create thread 1 failed\n);return -1;}usleep(1000000);if (pthread_create(hThread2, NULL, threadFunc2, NULL) ! 0){printf(create thread 2 failed\n);return -1;}pthread_join(hThread1, NULL);pthread_join(hThread2, NULL);pthread_rwlock_destroy(m_lock);return 0; }读优先则没有死锁的问题可以正常的执行下去。 thread 1 running.. thread 1 read source A0 thread 2 running.. thread 1 read source B0 thread 2 write source A and B通过上面的实验当reader lock需要重入时需要很谨慎一旦读写锁的属性是写优先那么很有可能会产生死锁。 总结 读写锁适用于读多写少的场景在这种场景下可能会有一些性能收益读写锁的使用上存在着一些陷阱平常尽量用互斥锁(mutex)代替读写锁。
http://www.yutouwan.com/news/12486/

相关文章:

  • 凡高网站建设通过骗子网站能找到其服务器吗
  • 百度收录网站的图片google网站
  • 随州制作网站河南移动商城网站建设
  • 如何做简单网站首页怎么设置wordpress页面
  • 百度有哪些网站可免费做软件推广为什么很少用python做网站
  • 镇海建设交通局网站seo推广软
  • 建设银行贵金属网站一个网站做无限关键词
  • 商城网站开发多少钱wordpress 管理入口
  • 网站备案 途径淮滨网站建设
  • 企业为什么需要建站wordpress主题国外优秀
  • 抚松网站建设门户网站建设自查整改
  • 转转网站怎么建设上海英文网站制作
  • 江苏常州青之峰做网站提供东莞微信网站建设
  • 外贸网站建设 广州php视频网站怎么做
  • 手机网站建设口碑好大桥外语官方网站星做宝贝
  • 网站属于什么公司外发加工费计入什么科目
  • 网站站点建设端口号的作用百度竞价账户
  • 想做网站濮阳网站建设怎么看网站有没有做404
  • 网站建设培训心得wordpress 人体时钟
  • 网站开发 网页设计北京师范大学出版社知名网站制作公司青岛分公司
  • 南昌做网站公司大蒜价格国际贸易网
  • asp 网站开发实例教程安徽省建设厅官网查询
  • 深圳网站建设价格多少钱安阳网站设计哪家好
  • 济南高新网站建设简单大气的科技公司名字
  • 建设网站如入什么费wordpress 安装 模板
  • 怎样用js做网站轮播图西安千秋网络科技有限公司怎么样
  • 东莞网站建设专业品牌武进网站建设效果
  • 有没有什么做地堆的网站照片素材库网站免费
  • 北京公司网站建设服务阿里云一个域名做两个网站
  • 水泥制品做阿里巴巴还是网站好泰安市人才信息网