96SEO 2026-02-20 00:20 0
五、条件变量1、背景概念2、初始化与销毁3、等待1函数2参数意义3互斥锁的作用

六、生产者消费者模型1、概念2、示意图3、优点4、环形队列1示意图2说明
临界资源互斥资源为多线程执行流共享的资源。
临界区为每个线程内部访问临界资源的程序段代码。
互斥为任何时刻都保证有且只有一个执行流进入临界区访问临界资源通常对临界资源起保护作用。
原子性为所进行的操作不会被任何调度机制打断。
该操作只有两态即完成态和未完成态而没有中间状态。
使用互斥锁的本质是用时间来换取安全表现为线程对于临界区代码串行执行原则上是尽量的要保证临界区代码越少越好。
因为锁本身就是共享资源所以申请互斥锁和释放互斥锁的操作被设计成原子性操作。
在纯互斥环境下如果锁分配不够合理就容易导致其他线程的饥饿问题。
在临界区中线程可以被切换但在线程被切换出去的时候其是持有锁被切换的。
在这期间没有谁能进入该互斥锁所锁定的临界区去访问临界资源。
持有互斥锁的线程访问临界区的过程对于其他线程来说是原子的。
pthread_mutex_init函数将使用attr指定的属性初始化mutex引用的互斥锁。
如果attr为NULL则使用默认的互斥属性其效果与传递默认互斥属性对象的地址的效果相同。
只有互斥锁本身可用于执行同步。
在调用pthread_mutex_lock函数、pthread_mutex_trylock函数、pthread_mutex_unlock函数和pthread_mutex_destroy函数时引用互斥锁副本的结果是未定义的。
在默认互斥锁属性适用的情况下宏PTHREAD_MUTEX_INITIALIZER可用于初始化静态分配的互斥锁。
该效果等同于通过调用pthread_mutex_init函数并将参数attr指定为NULL进行动态初始化但不执行错误检查。
尝试初始化已初始化的互斥锁的行为是未定义的。
初始化成功后互斥锁的状态将被初始化且为解锁状态。
pthread_mutex_destroy函数的作用为将mutex引用的互斥对象销毁。
互斥对象实际上会变成未初始化。
即pthread_mutex_destroy函数会将mutex引用的对象设置为无效值。
被销毁的互斥对象可以使用pthread_mutex_init函数重新初始化。
而在对象被销毁后以其他方式引用该对象的结果是未定义的。
销毁已解锁且初始化的互斥锁是安全的而试图销毁锁定的互斥锁会导致未定义的行为。
使用
初始化的互斥锁不需要调用pthread_mutex_destroy函数销毁。
mutex引用的互斥对象可通过调用pthread_mutex_lock函数来锁定。
如果该互斥锁已被锁定则调用的线程会进行阻塞等待直到互斥锁可用。
此操作申请锁成功将返回处于锁定状态的互斥对象调用线程作为其所有者。
申请互斥锁成功后尝试重新锁定互斥锁会导致死锁。
如果一个线程试图解锁它没有锁定的互斥锁或处于解锁状态的互斥锁则会导致未定义的行为返回错误。
pthread_mutex_trylock函数等效于pthread_mutex_lock函数但如果mutex引用的互斥对象当前被锁定已被任何线程包括当前线程申请成功则调用会立即返回。
pthread_mutex_unlock函数释放mutex引用的互斥对象。
而互斥锁的释放方式取决于互斥锁的类型属性。
如果在调用pthread_mutex_unlock函数时mutex引用的互斥对象上有线程被阻塞则当互斥对象可用时调度策略应确定哪个线程应获取该互斥对象。
如果一个信号被传递给等待互斥锁的线程那么在信号处理程序返回时线程应继续等待之前等待的互斥锁就像该线程没有被中断一样。
*lock*/)//:_lock(lock){_threadName
static_castthreadData*(args);while(true){pthread_mutex_lock(lock);//pthread_mutex_lock(td-_lock);cout
endl;pthread_mutex_unlock(lock);//pthread_mutex_unlock(td-_lock);if(count
lock*/);tds.push_back(td);pthread_create(tid,
td);tids.push_back(tid);}for(auto
endl;//pthread_mutex_destroy(lock);return
如果线程是安全的则多个线程并发执行同一段代码时不会出现不同的结果。
在没有锁保护的情况下对全局变量或者静态变量进行操作会出现线程安全问题。
重入为同一个函数被不同的执行流调用时当前一个流程还没有执行完就有其他的执行流再次进入。
一个函数在重入的情况下运行结果不会出现任何不同或者任何问题则该函数为可重入函数。
否则则为不可重入函数。
不保护共享变量的函数。
函数状态随着被调用状态发生变化的函数。
返回指向静态变量指针的函数。
调用线程不安全函数的函数。
两个或两个以上的线程在执行过程中因争夺资源而造成的一种互相等待的现象若无外力作用它们都将无法推进下去。
此时系统处于死锁状态或系统产生了死锁。
这些永远在互相等待的线程为死锁线程。
在死锁情况下所占用的资源或者需要它们进行某种合作的其它线程会相继陷入死锁最终可能导致整个系统处于瘫痪状态。
互斥条件一个资源每次只能被一个执行流使用。
这是产生死锁的前提。
请求与保持条件一个执行流因请求资源而阻塞时对已获得的资源保持不放。
这是产生死锁的原则。
不剥夺条件一个执行流已获得的资源在末使用完之前不能强行剥夺。
这是产生死锁的原则。
循环等待条件若干执行流之间形成一种头尾相接的循环等待资源的关系。
这是产生死锁的重要条件。
破坏四个必要条件。
加锁的顺序一致。
避免锁未释放的场景。
资源一次性分配。
同步在保证数据安全的前提下让线程能够按照某种特定的顺序访问临界资源从而有效避免饥饿问题。
竞态条件因为时序问题导致程序异常。
条件变量是一种线程同步的基本机制用于线程之间发信号通知和等待。
它通常和互斥锁一起使用以防止竞态条件和确保线程安全。
即条件变量必须依赖于锁的使用。
条件变量的优点是可以以原子方式阻塞线程直到某个特定条件为真为止。
参数cond表示调用该函数的线程要在这个条件变量上等待。
参数mutex表示当线程申请不到mutex时在条件变量cond下等待。
在等待时如果不能申请到条件变量则会释放锁mutex。
条件等待是线程间同步的一种手段如果只有一个线程条件不满足会一直等下去所以必须要有一个线程通过某些操作改变共享变量使原先不满足的条件变得满足并且友好的通知等待在条件变量上的线程。
条件不会无缘无故的突然变得满足这必然会牵扯到共享数据的变化。
所以需要用互斥锁来保护没有
pthread_cond_broadcast函数可解除当前阻塞在指定条件变量cond上的所有线程。
如果在cond上有任何线程被阻塞pthread_cond_signal函数可解除当前阻塞在指定条件变量cond上的至少一个线程。
如果当前没有线程阻塞在条件变量cond上则pthread_cond_broadcast和pthread_cond_signal函数将无效。
{pthread_detach(pthread_self());uint64_t
endl;while(true){pthread_mutex_lock(lock);//此处可加判断语句不满足再在条件变量下等待pthread_cond_wait(cond,
endl;pthread_mutex_unlock(lock);}
(void*)i);usleep(1000);}while(true){sleep(2);//pthread_cond_signal(cond);//cout
endl;pthread_cond_broadcast(cond);cout
释放pthread_cond_signal以及下一行的注释注释pthread_cond_broadcast以及下一行
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯而通过阻塞队列来进行通讯。
所以生产者生产完数据之后不用等待消费者处理而是直接扔给阻塞队列消费者不找生产者要数据而是直接从阻塞队列里取。
阻塞队列相当于一个缓冲区平衡生产者和消费者的处理能力和用来给生产者和消费者解耦。
生产者和生产者之间是互斥关系、消费者和消费者之间是互斥关系、生产者和消费者之间是互斥且同步关系。
模型包括两种角色生产者和消费者。
模型需要一个交易场所即特定结构的内存空间。
当环形队列满和空时head和tail指向的是同一个位置。
此时只能一方进行访问当队列空时生产者进行访问当队列满时消费者进行访问。
消费者不能超过生产者生产者不能超过消费者一个环形队列的长度
信号量是一个计数器用于限制对共享资源的访问数量。
当多个线程或进程需要访问共享资源时它们会先尝试获取信号量。
如果信号量的值大于0则允许一个线程或进程获取信号量并访问共享资源然后将信号量的值减1。
否则则会等待。
信号量把判断资源是否就绪放在了临界区之外当申请信号量时其实间接得在判断资源是否就绪。
sem_init函数的作用为在sem指向的地址初始化未命名的信号量。
value参数指定信号量的初始值。
pshared参数指示此信号量是在进程的线程之间共享还是在进程之间共享。
如果pshared的值为0则信号量在进程的线程之间共享并且应该位于所有线程可见的某个地址。
如全局变量或在堆上动态分配的变量。
如果pshared为非零则信号量在进程之间共享并且应该位于共享内存区域中。
任何可以访问共享内存区域的进程都可以使用sem_post、sem_wait等对信号量进行操作。
初始化已初始化的信号量的行为是未定义。
sem_destroy函数的作用为销毁sem指向的地址处的未命名信号量。
只有由sem_init函数初始化的信号量才应该使用sem_destroy函数销毁。
销毁当前有其他进程或线程被阻塞的信号量即其在sem_wait中会产生未定义的行为。
使用已被销毁的信号量会产生未定义的结果除非使用sem_init函数重新初始化该信号量。
sem_wait函数递减锁定sem指向的信号量。
如果信号量的值大于零则递减继续进行函数立即返回。
如果信号量当前的值为零则调用会阻塞直到可以执行递减即信号量值升至零以上或者信号处理程序中断该调用。
sem_post函数递增解锁sem指向的信号量。
如果信号量的值因此变得大于零则sem_wait调用中阻塞的另一个进程或线程将被唤醒并继续进行锁定信号量的操作。
Pattern是一种设计模式。
这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类该类负责创建自己的对象同时确保只有单个对象被创建。
这个类提供了一种访问其唯一的对象的方式全局访问点可以直接访问不需要实例化该类的对象。
饿汉模式是一种设计模式它在类加载时就完成了实例化操作。
因此在类加载时比较慢但在获取对象时速度比较快。
它的优点是实现简单线程安全。
因为实例在类加载时就已经创建所以不存在多线程下的同步问题。
它的缺点是在类加载时就完成了实例化如果这个类在程序运行过程中从未被使用到那么就会造成资源的浪费。
懒汉模式是一种在类加载时不进行实例化只有在首次调用时才创建实例的设计模式。
它的实现通常需要使用到同步机制来保证线程安全。
它的优点是可以延迟实例化只有在实际需要时才会创建对象。
它的缺点是线程不安全在多线程环境下如果没有正确的同步机制就可能会出现多个实例的情况。
悲观锁在每次取数据时总是担心数据会被其他线程修改。
所以会在取数据前先加锁读锁写锁行锁等当其他线程想要访问数据时会被阻塞挂起。
乐观锁在每次取数据的时总是乐观的认为数据不会被其他线程修改因此不上锁。
但是在更新数据前会判断其他数据在更新前有没有对数据进行修改。
主要采用两种方式即版本号机制和CAS操作。
CAS操作当需要更新数据时判断当前内存值和之前取得的值是否相等。
如果相等则用新值更新。
若不相等则失败失败则重试一般是一个自旋的过程即不断重试。
读写锁专门处理多读少写的情况写时独占锁读时共享锁读锁的优先级比写锁高。
写者之间是互斥竞争关系写者与读者之间是互斥同步关系读者之间是共享关系。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback