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

vs做网站图片明明在文件夹里却找不到网站怎么优化搜索

vs做网站图片明明在文件夹里却找不到,网站怎么优化搜索,品牌建设存在的问题,电子商务网站建设 试卷目录 线程概念线程控制创建退出等待join实例detach实例 实例 线程安全概念互斥同步生产者与消费者模型实例 信号量 线程应用 线程概念 线程概念: 有一个零件加工工厂,工厂中有一个或多个工人 工人是干活的,工厂是集体设备资源的载体 进程就是…

目录

  • 线程概念
  • 线程控制
    • 创建
    • 退出
    • 等待
      • join实例
      • detach实例
    • 实例
  • 线程安全
    • 概念
    • 互斥
    • 同步
    • 生产者与消费者模型
      • 实例
    • 信号量
  • 线程应用

线程概念

线程概念
有一个零件加工工厂,工厂中有一个或多个工人
工人是干活的,工厂是集体设备资源的载体
进程就是工厂,线程就是工人。
进程是系统进行资源分配的基本单元;线程是系统进行调度的基本单元。
线程就是进程中的一条执行流程。Linux下线程执行流程是通过pcb实现的,而一个进程中可以有多个线程(pcb),并且这些pcb共享了进程中的大部分资源,相较于传统pcb较为轻量化,因此linux下的线程也被称作为轻量级进程。
通俗理解:在最早学习进程的时候,认为进程就是pcb,是一个程序运行的动态描述,通过这个描述符操作系统实现程序运行调度以及管理。
但是在学习到线程的时候,才知linux下的pcb实际上是一个线程,是进程中的一条执行流程,一个进程中可以有多个pcb,这些pcb共享进程中的大部分资源,因此也被成为轻量级进程。

线程间的独有与共享
独有:标识符,栈,寄存器,信号屏蔽字,errno…
共享:虚拟地址空间,IO信息,信号处理方式,工作路径…
多进程与多线程进行多任务处理的优缺点
线程优点
1.线程间通信更加灵活(包括进程间通信方式在内还可以使用全变量或者函数传参来实现)
2.线程的创建与销毁成本更低。
3.线程间的切换调度成本更低。
进程优点
稳定,健壮性高。—主程序安全性要求高的场景–shell、服务器
多任务处理中,并不是进程或者线程越多越好。执行流太多反而会增加切换调度的成本。
IO密集型程序:程序中大量进行IO操作
cpu密集型程序:程序汇总大量进行数据运算操作

线程控制

线程控制:创建,退出,等待,分离
linux并没有向上提供用于创建线程的接口,因此大牛们对系统调用接口进行封装实现了上层用户态的线程控制接口

创建

int pthread_create(pthread_t *tid, pthread_attr_t *attr, void*(*thread_routine)(void*), void *arg)

参数说明
pthread_t *tid:用于获取线程id,tid是线程的操作句柄,实际上是线程在虚拟地址空间中自己所相对独有的一块空间的首地址
pthread_attr_t *attr:用于线程属性设置
void*(*)(void*):线程入口函数
void *arg:传递给线程的数据
返回值:成功返回0;失败返回非0值

pthread_self()
返回线程id

退出

退出:如何退出线程
线程入口函数中return(线程入口函数运行完毕,则线程会退出)
主线程main函数中return退出的是进程

void pthread_exit(void *retval);

void pthread_exit(void *retval); 在任意位置调用都可以退出线程
主线程退出,并不会导致进程退出;所有线程退出,才会退出进程
进程退出,会退出所有的线程

int pthread_cancel(pthread_t thread);

int pthread_cancel(pthread_t tid);
取消指定的线程(被动退出)

等待

等待:等待一个指定的线程退出,获取退出线程的返回值,回收线程资源。
线程推出后,默认也不会自动释放资源,需要被等待。
处于joinable状态的线程退出后不会自动释放资源

//阻塞接口
int pthread_join(pthread_t tid, void **retval)

tid:指定要等待的线程id;
retval:用于获取退出线程返回值
返回值:成功返回0;失败返回非0-错误编号;

join实例

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>void *thr_entry(void *arg)
{char *ptr = "nice day\n";sleep(3);return (void*)ptr;
}
int main(int argc, char *argv[])
{pthread_t tid;int ret = pthread_create(&tid, NULL, thr_entry, NULL);if(ret != 0){ printf("thread create error\n");return -1;}void *retval = NULL;pthread_join(tid, &retval);printf("retval:%s\n", retval);while(1){printf("i am main thread\n");sleep(1);}return 0;
}

线程有个属性-分离属性,这个属性默认是joinable状态,处于joinable的线程推出之后不会自动释放资源,需要被其他线程等待。
分离:将线程的分离属性,设置为detach状态
处于detach状态的线程退出后,会自动释放资源,不需要被等待。
应用场景:不关心线程的退出返回值,也不想等待一个线程退出

int pthread_detach(pthread_t tid);

detach实例

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>void *thr_entry(void *arg)
{char *ptr = "nice day\n";sleep(3);return (void*)ptr;
}
int main(int argc, char *argv[])
{pthread_t tid;int ret = pthread_create(&tid, NULL, thr_entry, NULL);if(ret != 0){ printf("thread create error\n");return -1;}pthread_detach(tid);//void *retval = NULL;//pthread_join(tid, &retval);//printf("retval:%s\n", retval);while(1){printf("i am main thread\n");sleep(1);}return 0;
}
## 查看
```powershell
ps -ef -L | grep create

ps -ef | grep create:查看create程序的进程信息
-L:查看轻量级进程信息
在每个线程的pcb中都有一个pid和tgid
pid是轻量级进程id-LWP;tgid是线程组id-默认等于主线程的pid
tid:这是一个地址–线程独有空间的地址
每个线程被创建,都会在进程的虚拟地址空间中开辟出一块相对独立的空间

实例

//create.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>void *thr_entry(void *arg)
{printf("%s\n", (char*)arg);while(1){printf("i am normal thread--%p-%d\n", pthread_self(), getpid());sleep(5);pthread_exit(NULL);}return NULL;
}
int main(int argc, char *argv[])
{pthread_t tid;int ret;char *ptr = "nice day\n";ret = pthread_create(&tid, NULL, thr_entry, (void*)ptr);if(ret != 0){printf("pthread_create failed!\n");return -1;}//sleep(3);//pthread_cancel(tid);while(1){//打印线程id和进程idprintf("i am main thread--%p-%d\n", pthread_self(), getpid());sleep(1);}return 0;
}

线程安全

概念

概念:描述的是线程中对临界资源的访问操作是安全的
实现:同步与互斥
同步通过条件判断使对临界资源访问或获取更加合理
互斥通过对临界资源同一时间的唯一访问保证访问操作安全

互斥

互斥的实现:互斥锁
互斥锁:本质就是一个只有0/1的计数器,用于标记临界资源的访问状态;0-不可访问;1-可访问。
实现互斥原理,在访问临界资源之前加锁:通过计数器判断是否可访问,不可访问则阻塞;访问资源完毕之后解锁:通过计数器将资源标记为可访问,唤醒阻塞。
互斥锁自身计数的操作是一个原子操作
接口介绍:
1.定义互斥锁变量
pthread_mutex_t mutex;
2.初始化互斥锁变量
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
3.在访问临界资源之前加锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);加锁失败则立即返回错误编号-EBUSY
4.在访问临界资源之后解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
5.销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>int tickets = 100;void *scalpers(void *arg)
{pthread_mutex_t *mutex = (pthread_mutex_t*)arg;while(1){pthread_mutex_lock(mutex);if(tickets > 0){usleep(1);printf("I got a ticket: %d\n", tickets);tickets--;}else{pthread_exit(NULL);pthread_mutex_unlock(mutex);}pthread_mutex_unlock(mutex);}return NULL;
}
int main(int argc, char *argv[])
{pthread_mutex_t mutex;pthread_t tid[4];int ret;pthread_mutex_init(&mutex, NULL);for(int i = 0; i < 4; i++){ret = pthread_create(&tid[i], NULL, scalpers, &mutex);if(ret != 0){printf("thread create error\n");return -1;}}for(int i = 0; i < 4; i++){pthread_join(tid[i], NULL);}pthread_mutex_destroy(&mutex);return 0;
}

死锁:程序运行流程因为某种原因卡死无法继续推进
死锁产生的原因:死锁产生的四个必要条件
1.互斥条件:一个资源同一事件只有一个进程/线程能够访问
2.不可剥夺条件:我加的锁只有我能解,别人不能解
3.请求与保持条件:加了A锁后请求B锁,B请求不到,A不释放
4.环路等待条件:线程1加了A锁,请求B锁;线程2加了B请求A
预防死锁:破坏死锁产生的必要条件(3.4)
1.一定保证加/解锁顺序一致
2.请求不到第二个锁则释放已有的
避免死锁:银行家算法
已有资源—线程已有资源—线程请求新的资源

同步

同步的实现:通过条件判断实现对资源获取的合理性–条件变量
条件变量:pcb等待队列+能够使线程阻塞以及唤醒线程阻塞的接口
条件变量使用中,对条件判断由程序员自己完成,而条件判断的依据使一个临界资源,访问时需要被保护,因此条件变量需要搭配互斥锁一起使用。

接口介绍
1.定义条件变量
pthread_cond_t cond;
2.初始化条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);
3.使线程阻塞
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *abstime)
4.唤醒阻塞的线程:
int pthread_cond_signal(pthread_cond_t *cond);-至少唤醒一个
int pthread_cond_broadcast(pthread_cond_t *cond);-唤醒所有
5.销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);

注意:条件变量需要搭配互斥锁一起使用;
因此资源是其他线程促使条件满足,其中的条件是否满足也是临界资源的判断。因此需要加锁保护。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>pthread_mutex_t mutex;
pthread_cond_t cond_customer;
pthread_cond_t cond_cooker;
int bowl = 1;
void *cooker(void *arg)
{while(1){//lockpthread_mutex_lock(&mutex);while(bowl == 1){//waitpthread_cond_wait(&cond_cooker, &mutex);}//cookprintf("cook finish\n");bowl++;//wake customerpthread_cond_signal(&cond_customer);//unlockpthread_mutex_unlock(&mutex);}return NULL;
}
void *customer(void *arg)
{//lock  pthread_mutex_lock(&mutex);while(1){while(bowl == 0){//waitpthread_cond_wait(&cond_customer, &mutex);}//eatprintf("nice\n");bowl--;//wake cookerpthread_cond_signal(&cond_cooker);//unlockpthread_mutex_unlock(&mutex);}return NULL;
}
int main(int argc, char *argv[])
{pthread_t ctid, dtid;int ret;pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond_customer, NULL);pthread_cond_init(&cond_cooker, NULL);for(int i = 0; i < 4; i++){ret = pthread_create(&ctid, NULL, cooker, NULL);if(ret != 0){printf("thread create error\n");return -1;}}  for(int i = 0; i < 4; i++){ret = pthread_create(&dtid, NULL, customer, NULL);if(ret != 0){printf("thread create error\n");return -1;}}pthread_join(ctid, NULL);pthread_join(dtid, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond_customer);pthread_cond_destroy(&cond_cooker);return 0;
}

注意事项
一、条件变量使用过程中,条件的判断应该使用循环操作
1.四个顾客因为没有饭陷入阻塞
2.厨师做好饭,唤醒了四个顾客
3.四个顾客中,一个加锁成功吃饭,三个卡在加锁这里
4.加锁成功的顾客吃完饭唤醒厨师解锁
5.有可能抢到锁的不是厨师而是顾客
6.如果没有循环判断则会加锁成功后在没有饭时吃饭
二、条件变量使用过程中,若有多种角色则需要使用多个条件变量,不同的角色,分开等待,分开唤醒,防止唤醒角色错误

生产者与消费者模型

生产者与消费者模型:一种非常典型的设计模式。
设计模式:大佬们针对典型的应用场景设计的解决方案
应用场景:有大量数据产生以及进行处理的场景
优势:解耦合,支持忙闲不均,支持并发
实现:两种角色的线程+线程安全的队列(阻塞队列)
线程安全
生产者与生产者:互斥
消费者与消费者:互斥
生产者与消费者:同步+互斥
线程安全的阻塞队列的实现

实例

#include <iostream>
#include <queue>
#include <pthread.h>#define MAX_QUEUE 5
class BlockQueue
{
private:int _capacity;//容量std::queue<int> _queue;pthread_mutex_t _mutex;pthread_cond_t _cond_pro;pthread_cond_t _cond_cus;
public:BlockQueue(int cap = MAX_QUEUE): _capacity(cap){pthread_mutex_init(&_mutex, NULL);pthread_cond_init(&_cond_pro, NULL);pthread_cond_init(&_cond_cus, NULL);}~BlockQueue(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond_pro);pthread_cond_destroy(&_cond_cus);}bool Push(int data){pthread_mutex_lock(&_mutex);while(_queue.size() == _capacity){pthread_cond_wait(&_cond_pro, &_mutex);}_queue.push(data);pthread_cond_signal(&_cond_cus);pthread_mutex_unlock(&_mutex);return true;}bool Pop(int *data){pthread_mutex_lock(&_mutex);while(_queue.empty){pthread_cond_wait(&_cond_cus, &_mutex);}*data = _queue.front();_queue.pop();pthread_cond_signal(&_cond_pro);pthread_mutex_unlock(&_mutex);return true;}
};void *productor(void *arg)
{BlockQueue *q = (BlockQueue*)arg;int i = 0;while(1){q->Push(i);printf("%p-push data:%d\n", pthread_self(), i++);}return NULL;
}
void *customer(void *arg)
{BlockQueue *q = (BlockQueue*)arg;while(1){int data;q->Pop(&data);printf("%p-get data:%d\n", pthread_self(), data);}return NULL;
}
int main(int argc, char *argv[])
{BlockQueue q;int count = 4, ret;pthread_t ptid[4], ctid[4];for(int i = 0; i < count; i++){ret = pthread_creat(&ptid[i], NULL, productor, &q);if(ret != 0){	printf("thread create error\0");return 0;}}for(int i = 0; i < count; i++){ret = pthread_creat(&ctid[i], NULL, customer, &q);if(ret != 0){	printf("thread create error\0");return 0;}}for(int i = 0; i < count; i++){pthread_join(ptid[i], NULL);pthread_join(ctid[i], NULL);}return 0;
}

信号量

信号量
本质:计数器
作用:实现进程或线程间的同步与互斥
操作
P操作:计数-1,计数<0则阻塞执行流
V操作:计数+1,唤醒一个阻塞的执行流
同步的实现:通过对计数器对资源进行计数
在获取资源之前,进行P操作;产生资源之后,进行V操作
互斥的实现:初始化值为1,表示资源只有一个
在访问资源之前进行P操作;访问完毕之后进行V操作

接口认识:
1.定义信号量:sem_t sem;
2.初始化信号量
int sem_init(sem_t *sem, int pshared, unsigned int value)
sem:信号量;
pshared:0-线程间/!0-进程间;
value:要设置的初值;
返回值:成功返回0;失败返回-1。
3.P操作:
int sem_wait(sem_t *sem);-阻塞
int sem_trywait(sem_t *sem);-非阻塞
int sem_timedwait(sem_t *sem, struct timespec *timeout);
4.V操作:
int sem_post(sem_t *sem);
5.销毁信号量:
int sem_destroy(sem_t *sem);

线程应用

http://www.tj-hxxt.cn/news/13218.html

相关文章:

  • 做一个网站需要服务器吗网络营销课程个人总结3000字
  • 重庆网站建设设计公司网络优化的内容包括哪些
  • 商城网站数据库表关系设计新站如何让百度快速收录
  • 网站用户注册怎么做企业网络营销顾问
  • 网站咨询弹窗是怎么做的灰色词排名接单
  • 门户网站设计思路襄阳seo培训
  • 在国外做盗版电影网站怎么样推广自己的店铺和产品
  • 上海一条网络科技有限公司搜索引擎优化是指什么意思
  • 室内设计方案英文关键词seo
  • 甘肃手机网站建设石家庄seo推广
  • 系统搭建方案肇庆seo
  • 做网站怎么做多少钱网站seo优化方案项目策划书
  • 徐州cms建站系统qq群推广
  • 合肥如何做百度的网站推广搜索引擎营销的方法有哪些
  • 宁波品牌网站制作哪家好品牌运营管理有限公司
  • 最常用的网页制作工具广州seo运营
  • pathon做网站关键词歌曲免费听
  • 网站建设中的需求报告功能app优化排名
  • 溧阳网站建设哪家好百度竞价有点击无转化
  • 上饶市住房城乡建设局网站seo外包优化网站
  • 做网站的叫什么职位郑州seo外包v1
  • 专业网站公司交换链接名词解释
  • wordpress 输出the idseo营销推广全程实例
  • 农业网站建设模板下载网络营销公司热线电话
  • dede网站301怎么做线上推广营销
  • 网站中如何做图片轮播百度快照推广是什么意思
  • 高端+旅游+网站建设广州短视频代运营
  • 跨境电商什么产品最火百度seo快排软件
  • 营销方案格式魔贝课凡seo课程好吗
  • 网上建设网站一键建站免费