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

打赏网站怎么建设女与男爱做电影网站免费

打赏网站怎么建设,女与男爱做电影网站免费,营业执照网上年检入口,2021搜索引擎排名目录 一、概念 二、互斥锁实现互斥 三、条件变量实现同步 银行家算法 生产者与消费者模型 一、概念 概念:在多线程程序中,如果涉及到了对共享资源的操作,则有可能会导致数据二义性,而线程安全就指的是,就算对共享…

目录

一、概念

二、互斥锁实现互斥

三、条件变量实现同步

        银行家算法

生产者与消费者模型


一、概念

概念:在多线程程序中,如果涉及到了对共享资源的操作,则有可能会导致数据二义性,而线程安全就指的是,就算对共享资源进行操作也不会导致数据二义

实现:如何实现多线程中对共享资源的操作不会出问题

        互斥:通过同一时间对资源访问的唯一性,保证访问安全

                 互斥的实现:互斥锁(读写锁、自旋锁...)

        同步:通过条件控制,让多执行对资源的获取更加合理

                 同步实现:条件变量、信号量

二、互斥锁实现互斥

实现对共享资源的唯一访问

1)互斥锁实现互斥的原理

        本质:就是一个1/0计数器,通过0/1标记资源的访问状态(0-不可访问、1-可访问)

                   在访问资源之前进行加锁(通过状态判断是否可访问,不可访问则阻塞)

                   在访问资源之后进行解锁(将资源状态置为可访问状态,唤醒其他阻塞的线程)

        也有另一种理解:访问资源之前加锁(获取锁资源-获取不到就阻塞)

                                     访问完毕解锁(归还锁资源)

        多个线程想要实现互斥,就必须访问同一个锁才可以,也就意味着锁也是一个共享资源

 互斥锁的操作本身必须是安全的:互斥锁本身计数器的操作时原子操作

2)互斥锁如何实现自身操作安全的原理

 我们知道内存与cpu之间的数据传输:当进行加锁操作时,先将锁中的1置入cpu(先将变量数据从内存加载到cpu)然后才能从cpu中对数据进行处理(转化为0)然后在从cpu中将数据加载到内存指定位置(完成将1替换为0)

然而这样一种操作就会产生问题,如果1从内存加载到cpu还没有将处理后的0加载回内存时,这时切换其他线程运行访问到的锁资源仍然为1,就会继续进行加锁,这无疑是致命的。

所以对于锁资源本身来说,计数器的操作必须是原子性的才可以。

有个指令类似于exchange,功能是交换指定寄存器与内存中的数据

        1、先将指定寄存器中的值修改为0,

        2、将寄存器与内存中的数据进行互换

        3、判断是否符合获取锁的条件或者说判断是否能够加锁

 这样使用exchange指令就可以实现计数器操作为原子操作。

3)接口

互斥锁类型变量      pthread_mutex_t

初始化互斥锁

        int pthread_mutex_init(pthread_mutex_t *mutex,  pthread_mutexattr_t *attr)

                mutex:互斥锁变量的地址        attr:互斥锁变量属性(通常置NULL)

访问资源前加锁

        int pthread_mutex_lock(pthread_mutex_t *mutex)        阻塞加锁(老实人)

        int pthread_mutex_trylock(pthread_mutex_t *mutex)        非阻塞加锁(海王)

访问资源后解锁

        int pthread_mutex_unlock(pthread_mutex_t *mutex)

释放销毁互斥锁

        int pthread_mutex_destroy(pthread_mutex_t *mutex)

        pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER (这种初始化不需要销毁)

4)代码模拟

当不使用互斥锁线程之间对同一变量的访问情况如何?

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>int ticket = 100;
void *Scalper(void *arg)
{while(1){if(ticket > 0){usleep(10);printf("%p:我抢到了第 %d 号票\n",pthread_self(), ticket);ticket--;}else{printf("%p:票完了,我的工作结束了\n", pthread_self());break;}}return NULL;
}
int main()
{pthread_t tid[4];for(int i = 0; i < 4; i++){int ret = pthread_create(&tid[i], NULL, Scalper, NULL);if(ret != 0){perror("create error");return -1;}}for(int i = 0; i < 4; i++){pthread_join(tid[i], NULL);}return 0;
}

发现出现了很多意外情况,重复、负数票号,

为什么呢?就是因为每个线程之间访问同一变量,一个线程还正对变量进行操作的时候另一个线程也进行操作,于是就发生了同一变量的多次出现。

 使用互斥锁保护临界区

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>int ticket = 100;
void *Scalper(void *arg)
{while(1){pthread_mutex_lock(arg);    // 访问之前加锁if(ticket > 0){usleep(10);printf("%p:我抢到了第 %d 号票\n",pthread_self(), ticket);ticket--;pthread_mutex_unlock(arg);    // 在所有有可能退出的地方解锁}else{printf("%p:票完了,我的工作结束了\n", pthread_self());pthread_mutex_unlock(arg);    // 在所有有可能退出的地方解锁break;}usleep(1);}return NULL;
}
int main()
{pthread_mutex_t mutex;    // 定义锁变量 mutexpthread_mutex_init(&mutex, NULL);    // 初始化锁资源pthread_t tid[4];for(int i = 0; i < 4; i++){int ret = pthread_create(&tid[i], NULL, Scalper, &mutex); // 注意锁资源通过线程创建第四个参数传入入口函数内if(ret != 0){perror("create error");return -1;}}for(int i = 0; i < 4; i++){pthread_join(tid[i], NULL);}return 0;
}

5)死锁

死锁是一种状态,是一种因为资源争抢不当导致程序流程卡死无法继续向下推进的状态。

多个线程对锁资源的争抢使用不当导致程序流程卡死,无法继续向下推进的状态

1、加锁之后没有释放就退出,导致其他线程获取不到锁资源卡死

2、多锁使用时,加锁顺序不当,线程1加锁顺序为AB,线程2加锁顺序为BA

发生死锁的必要条件

        ① 互斥条件        同一时间一把锁只能被一个线程所获取到

        ② 不可剥夺条件        一个线程加的锁,只能自己释放,其他线程无法释放

        ③ 请求与保持        一个线程请求了A锁之后请求B锁,如果请求不到就不会释放A锁

        ④ 环路等待        线程1加了A锁后请求B锁,线程2加了B锁后请求A锁

死锁的预防:破坏死锁产生的必要条件

        ① 和 ② 无法修改

        写代码时要注意:

        1、线程之间的加解锁顺序尽量一致 -- 尽可能预防环路等待

        2、采用非阻塞加锁,如果加不上锁,则把已经加上的锁释放 -- 破坏请求与保持

                (请求不到新的,则释放已有的)

避免:银行家算法、死锁检测算法……

银行家算法http://t.csdn.cn/1YxZj

三、条件变量实现同步

1)概念

同步:通过条件控制,保证资源访问的合理性

条件变量:主要是一个pcb等待队列,以及唤醒和阻塞线程的接口

原理:

        线程1 获取资源时进行判断,如果线程不符合资源获取条件,则调用阻塞接口进行阻塞

        线程2 促使资源获取条件满足之后(生产资源),通过唤醒接口唤醒阻塞的线程

条件变量需要搭配互斥锁来使用

举例:

        顾客 与 厨师 (消费者与生产者)

顾客来到柜台,看到柜台有饭则吃饭,否则阻塞

厨师来到柜台,看到柜台上没有饭则做饭,否则阻塞

顾客:

        0、加锁(关门)

        1、访问柜台有没有饭

                有饭则吃饭,没有饭就阻塞

             (这里阻塞时需要进行解锁,否则厨师就无法访问柜台,也就无法做饭,产生死锁)

                阻塞则需先解锁,再阻塞,被唤醒之后再加锁

        2、吃饭

        3、吃完了,再来一碗       唤醒厨师

        4、解锁

厨师:

        0、加锁

        1、访问柜台有没有饭

                没饭则做饭,有饭则阻塞

                (这里是有饭就需要解锁,让顾客能够吃饭,否则会死锁)

                阻塞需先解锁,再阻塞,被唤醒后加锁

        2、做饭

        3、做好了,唤醒顾客

        4、解锁

2)接口

定义条件变量:

        pthread_cond_t 条件变量的变量类型

初始化条件变量:

        pthread_cond_t cond_init (pthread_cond_t *cond, pthread_condattr_t *attr);

阻塞接口:条件变量是搭配互斥锁一起使用的,就体现在阻塞这一步

        int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) -- 阻塞接口

        int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex,

                                                  struct timespec *t ) -- 有时长限制的阻塞

唤醒接口:

        int pthread_cond_signal(pthread_cond_t *cond)        唤醒至少一个阻塞队列中的线程

        int pthread_cond_broadcast(pthread_cond_t *cond)        唤醒等待队列中所有的线程

销毁接口:

        int pthread_cond_destroy(pthread_cond_t *cond)

3)模拟实现

#include<stdio.h>
#include<pthread.h>int counter = 0;    // 定义柜台状态 0——没饭   1——有饭 
pthread_mutex_t mutex;    // 初始化锁
pthread_cond_t cond;    // 初始化条件变量void* customer(void *arg)
{while(1){pthread_mutex_lock(&mutex);    // 先加锁if(counter==0){pthread_cond_wait(&cond, &mutex);    // 没饭则解锁 并阻塞,等待唤醒,唤醒后加锁}printf("真好吃,再来一碗\n");counter = 0;pthread_cond_signal(&cond);    // 吃完了唤醒厨师做饭pthread_mutex_unlock(&mutex);    // 解锁}
}void* cook(void *arg)
{while(1){pthread_mutex_lock(&mutex);    // 加锁if(counter == 1){pthread_cond_wait(&cond, &mutex);    // 有饭则 解锁并阻塞,等待唤醒,唤醒后加锁}printf("你的饭好了\n");counter = 1;pthread_cond_signal(&cond);    // 饭做好了唤醒顾客吃饭pthread_mutex_unlock(&mutex);    // 解锁}
}int main()
{pthread_mutex_init(&mutex, NULL);    // 初始化定义mutex 和 condpthread_cond_init(&cond, NULL);pthread_t cook_tid;    // 初始化定义线程ID(顾客和厨师)pthread_t cus_tid;int ret;ret = pthread_create(&cook_tid, NULL, cook, NULL);    // 分别创建对应线程if(ret != 0){perror("create error");return -1;}ret = pthread_create(&cus_tid, NULL, customer, NULL);if(ret != 0){perror("create error");return -1;}pthread_join(cook_tid, NULL);    // 执行线程等待pthread_join(cus_tid, NULL);pthread_mutex_destroy(&mutex);    // 执行mutex与cond的销毁pthread_cond_destroy(&cond);
}

 实现四个顾客四个厨师

在同步实现的代码中,如果存在多种角色,就应该定义多个条件变量,各自处于各自的pcb等待队列中。

#include<stdio.h>
#include<pthread.h>int counter = 0;
pthread_mutex_t mutex;
pthread_cond_t cond_cus;    // 使用不同的条件变量,防止死锁
pthread_cond_t cond_cook;
void* customer(void *arg)
{while(1){pthread_mutex_lock(&mutex);while(counter <= 0){pthread_cond_wait(&cond_cus, &mutex);}printf("真好吃,再来一碗: %d\n",counter);counter--;pthread_cond_signal(&cond_cook);pthread_mutex_unlock(&mutex);}
}void* cook(void *arg)
{while(1){pthread_mutex_lock(&mutex);while(counter > 0){pthread_cond_wait(&cond_cook, &mutex);}printf("你的饭好了:%d\n", counter);counter++;pthread_cond_signal(&cond_cus);pthread_mutex_unlock(&mutex);}
}int main()
{pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond_cus, NULL);pthread_cond_init(&cond_cook, NULL);pthread_t cook_tid[4];    // 定义四个顾客、四个厨师pthread_t cus_tid[4];int ret;for(int i = 0; i < 4; i++) // 创建这八个线程{ret = pthread_create(&cook_tid[i], NULL, cook, NULL);if(ret != 0){perror("create error");return -1;}ret = pthread_create(&cus_tid[i], NULL, customer, NULL);if(ret != 0){perror("create error");return -1;}}pthread_join(cook_tid[0], NULL);pthread_join(cus_tid[0], NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_cook);pthread_cond_destroy(&cond_cus);
}

 生产者与消费者模型

生产者与消费者模型icon-default.png?t=N176http://t.csdn.cn/GvZlZ

http://www.yayakq.cn/news/78621/

相关文章:

  • 礼品网站建设公司一个刚做好的网站怎么做seo
  • wordpress手机建站教程吉林市网站制作哪家好
  • 手机网站建设哪里好珠海公司制作网站
  • 网站开发用什么服务器sae wordpress 上传
  • 广州网站建设推荐q479185700顶上淘宝店铺推广方式有哪些
  • 著名的设计企业网站免费的网站模板有哪些
  • 服务好的南昌网站建设保定城乡建设局网站
  • 目前做那些网站能致富营销策略理论
  • 做随车吊网站要多大景观毕业设计作品网站
  • 网站集约化建设阿里云wordpress数据库备份
  • 做gif动态图网站智鼎互联网站建设
  • 企业网站怎么做seo帮助做职业规划的网站
  • 网站没有被搜索引擎收录做网站多少钱_西宁君博相约
  • 天津 响应式网站设计塘沽信息
  • wordpress仿站软件上海企业电话查询
  • 巴中做网站的公司电子商务网站建设答案
  • 诏安县城乡规划建设局网站微网站用什么做
  • 最新网站建设视频网站建设 app 优化
  • 微企点做网站怎么样能看的网址的浏览器
  • 网站建设 计入哪个科目找个男做那个视频网站好
  • 怎样做摄影网站凡科建站建网站
  • 品牌型网站制作有哪些公司个人网页设计界面
  • 湘潭建设公司网站如何把做的网站发布到网上
  • 公司网站制作费用申请太原网站建设pnjfw
  • 个人网站建站系统wordpress如何设置页面布局
  • p2p网站建设广州电子商务企业网站建设规划方案
  • 网站发布和收录怎么做中山专业外贸网站建设
  • 网站建设确认书mvc5 网站开发
  • 宁波小型建网站公司建筑工程网校排行榜
  • 华夏名网网站建设郑州教育网站建设