C++多线程同步总结

C++多线程同步总结

关于C++多线程同步

一、C++11规范下的线程库

1、C++11 线程库的基本用法:创建线程、分离线程

#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;
void threadProc()
{cout<<"this is in threadProc\n";cout<<"thread1's id is "<<this_thread::get_id()<<endl; //获取所属线程的id
}
void threadProc2(int num)
{cout<<"thread num = "<<num<<endl;
}
void threadProc3()
{cout<<"this thread is detached\n";
}
void threadProc4()
{cout<<"this thread is detached and won't print in the same console.'\n";
}
int main()
{thread a;//创建线程1,定义线程,后面再分配任务a = thread(threadProc);thread b(threadProc2,5);//创建线程2 ,定义线程的时候分配任务,参数类似于printf一样,可以为多个a.join();b.join();//采用join,主线程会阻塞等待子线程执行完毕thread c(threadProc3);c.detach();//采用detach,主线程不会等,这个线程开启早,还能输出到主线程的控制台cout<<"main thread exit"<<endl;thread d(threadProc4);d.detach();//
}

运行结果:

2、基本的互斥锁

上述运行,输出语句显然没有顺序执行,为了达到一行一行输出的效果,可以使用最基本的互斥锁。

#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex mu;//互斥锁 
void test1()
{for(int i=0;i<5;i++){
//        mu.lock();//锁住 cout<<"test1 i = "<<i<<endl;
//        mu.unlock();//释放 }
}
void test2()
{for(int j=0;j<5;j++){
//        mu.lock();cout<<"test2 j = "<<j<<endl;
//        mu.unlock();}
}
int main()
{thread a(test1);thread b(test2);a.join();b.join();cout<<"main thread finish."<<endl;
} 

运行结果:

不加锁的话,输出就会混乱。

这里打开4行注释,重新运行。

运行结果:

可以简单理解为:test1获得锁以后,test2调用lock(),就会阻塞执行,直到test1()调用unlock()释放锁。

3、lock_guard

#include <iostream>
#include <thread>
#include <mutex>mutex mu;//互斥锁 
/*
lock_guard<mutex> locka(mu);
作用范围为从这一行开始,到那一次循环结束,还不用自己手动解锁。 
*/
void test3()
{for(int i=0;i<5;i++){std::lock_guard<std::mutex> locka(mu); std::cout << "test3 i = "<< i << std::endl;}
}
void test4()
{for(int j=0;j<5;j++){std::lock_guard<std::mutex> lock(mu);std::cout << "test4 j = " << j << std::endl;}
}
int main()
{std::thread a(test3);std::thread b(test4);a.join();b.join();std::cout<<"main thread finish."<<std::endl;
} 

运行结果:

4、unique_lock

#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
mutex mu;//互斥锁 
void test5()
{for(int i=0;i<5;i++){unique_lock<mutex> locka(mu,defer_lock); cout<<"test5 i = "<<i<<endl;locka.lock();cout<<"this is lock1"<<endl;}
}
void test6()
{for(int j=0;j<5;j++){unique_lock<mutex> locka(mu); cout<<"test6 j = "<<j<<endl;locka.unlock();locka.lock();cout<<"this is lock2"<<endl;}
}
int main()
{thread a(test5);thread b(test6);a.join();b.join();cout<<"main thread finish."<<endl;
} 

运行结果:

 5、condition_variable

#include<iostream>
#include<thread>
#include<mutex>
#include<condition_variable>using namespace std;mutex mu;
condition_variable cv;
bool print = false;
void test7()
{for(int i=0;i<5;i++){unique_lock<mutex> l(mu);cout<<"test7 i = "<<i<<endl;cv.notify_one();print = true;}
}
void test8()
{for(int j=0;j<5;j++){unique_lock<mutex> l(mu);if(!print){cv.wait(l);}cout<<"test8 j = "<<j<<endl;print = false;}
}
int main()
{thread a(test7);thread b(test8);a.join();b.join();
}

运行结果:

二、Win32 API 实现线程同步

1、临界区

#include <iostream>
#include <thread>
#include <windows.h>using namespace std;CRITICAL_SECTION section;//临界区变量void test01()
{for(int i=0;i<5;i++){EnterCriticalSection(&section);//类似于 mutex.lock() cout<<"this is test01 i = "<<i<<endl;Sleep(1);LeaveCriticalSection(&section);//类似于 mutex.unlock() }
} 
void test02()
{for(int j=0;j<5;j++){EnterCriticalSection(&section);cout<<"this is test02 j = "<<j<<endl;Sleep(1);LeaveCriticalSection(&section);}
}
int main()
{InitializeCriticalSection(&section);//初始化临界区对象thread a(test01);thread b(test02);a.join();b.join();DeleteCriticalSection(&section);//用完了,就删除临界区 
}

运行结果:

效果类似于mutex,只是都要在执行完循环进行解锁的操作。

2、互斥锁

#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;
HANDLE hmutex;
void test03()
{for(int i=0;i<5;i++){WaitForSingleObject(hmutex,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 cout<<"test03 i = "<<i<<endl;ReleaseMutex(hmutex);//类似于mutex.unlock() 释放互斥锁 }
}
void test04()
{for(int j=0;j<5;j++){WaitForSingleObject(hmutex,INFINITE);cout<<"test04 j = "<<j<<endl;ReleaseMutex(hmutex);}
}
int main()
{hmutex = CreateMutex(NULL,FALSE,"mutex");//创建一个互斥锁 thread a(test03);thread b(test04);a.join();b.join();CloseHandle(hmutex);//释放句柄 
}

运行结果:

3、事件

#include<iostream>
#include<thread>
#include<windows.h>using namespace std;HANDLE hevent;
void test05()
{for(int i=0;i<5;i++){WaitForSingleObject(hevent,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 cout<<"test05 i = "<<i<<endl;SetEvent(hevent);//类似于mutex.unlock() 释放互斥锁 }
}
void test06()
{for(int j=0;j<5;j++){WaitForSingleObject(hevent,INFINITE);cout<<"test06 j = "<<j<<endl;SetEvent(hevent);}
}
int main()
{hevent = CreateEvent(NULL,FALSE,TRUE,"event");//创建一个事件 thread a(test05);thread b(test06);a.join();b.join();CloseHandle(hevent);//释放句柄 
}

运行结果:

4、信号量

#include <iostream>
#include <thread>
#include <windows.h>using namespace std;HANDLE sem;
void test07()
{for(int i=0;i<5;i++){WaitForSingleObject(sem,INFINITE);//类似于mutex.lock() 阻塞等待多少时间 cout<<"test07 i = "<<i<<endl;ReleaseSemaphore(sem,1,NULL);//类似于mutex.unlock() 释放互斥锁 }
}
void test08()
{for(int j=0;j<5;j++){WaitForSingleObject(sem,INFINITE);cout<<"test08 j = "<<j<<endl;ReleaseSemaphore(sem,1,NULL);}
}
int main()
{sem = CreateSemaphore(NULL,1,2,"semaphore");thread a(test07);thread b(test08);a.join();b.join();CloseHandle(sem);//释放句柄 
}

运行结果:

#include <iostream>
#include <fstream>
#include <random>
#include <ctime>#include <windows.h>
//#include <time.h>
#include <stdio.h>
#include <math.h>
#include <bitset>#include <thread>
#include <mutex>
#include <condition_variable>#define NAME_LINE   40
void* g_hMutex2 = NULL; //使用适当的初始化方式
//定义线程函数传入参数的结构体
typedef struct __TICKET
{int nCount;char strTicketName[NAME_LINE];__TICKET() : nCount(0){memset(strTicketName, 0, NAME_LINE * sizeof(char));}
}TICKET;typedef struct __THD_DATA
{TICKET* pTicket;char strThreadName[NAME_LINE];__THD_DATA() : pTicket(NULL){memset(strThreadName, 0, NAME_LINE * sizeof(char));}
}THD_DATA;//基本类型数据转换成字符串
template<class T>
std::string convertToString(const T val)
{std::string s;std::strstream ss;ss << val;ss >> s;return s;
}
//售票程序
DWORD WINAPI SaleTicket(LPVOID lpParameter);//售票系统
void Test2();// 一个mutex变量控制同一个资源,因此会先打印完*再打印$
// 两个mutex变量则可能出现交替打印,因为不是修改统一资源
std::mutex mtx;  // mutex for critical section
void print_block(int n, char c)
{mtx.lock();for (int i = 0; i<n; i++){std::cout << c;}std::cout << '\n';mtx.unlock();
}
void thread_1()
{std::cout << "子线程1" << std::endl;
}
void thread_2(int x)
{std::cout << "x:" << x << std::endl;std::cout << "子线程2" << std::endl;
}
int f_multi_thread()
{std::thread first(thread_1); // 开启线程,调用:thread_1()std::thread second(thread_2, 100); // 开启线程,调用:thread_2(100)//std::thread third(thread_2,3);//开启第3个线程,共享thread_2函数。std::cout << "主线程\n";first.join(); //join()等待线程结束并清理资源(会阻塞)        second.join();std::cout << "子线程结束.\n";//必须join完成//std::thread th1(print_block, 50, '*');//线程1:打印*//std::thread th2(print_block, 50, '$');//线程2:打印$//th1.join();//th2.join();return 0;
}void threadProc()
{std::cout << "this is in threadProc\n";std::cout << "thread1's id is " << std::this_thread::get_id() << std::endl; //获取所属线程的id
}
void threadProc2(int num)
{std::cout << "thread num = " << num << std::endl;
}
void threadProc3()
{std::cout << "this thread is detached\n";
}
void threadProc4()
{std::cout << "this thread is detached and won't print in the same console.'\n";
}
std::mutex mu;//互斥锁 
void test1()
{for (int i = 0; i < 5; i++){mu.lock();//锁住 std::cout << "test1 i = " << i << std::endl;mu.unlock();//释放 }
}
void test2()
{for (int j = 0; j < 5; j++){mu.lock();std::cout << "test2 j = " << j << std::endl;mu.unlock();}
}
/*
lock_guard<mutex> locka(mu);
作用范围为从这一行开始,到那一次循环结束,还不用自己手动解锁。
*/
void test3()
{for (int i = 0; i < 5; i++){std::lock_guard<std::mutex> locka(mu);std::cout << "test3 i = " << i << std::endl;}
}
void test4()
{for (int j = 0; j < 5; j++){std::lock_guard<std::mutex> lock(mu);std::cout << "test4 j = " << j << std::endl;}
}
void test5()
{for (int i = 0; i < 5; i++){std::unique_lock<std::mutex> locka(mu, std::defer_lock);std::cout << "test5 i = " << i << std::endl;locka.lock();std::cout << "this is lock1" << std::endl;}
}
void test6()
{for (int j = 0; j < 5; j++){std::unique_lock<std::mutex> locka(mu);std::cout << "test6 j = " << j << std::endl;locka.unlock();locka.lock();std::cout << "this is lock2" << std::endl;}
}
std::condition_variable cv;
bool print = false;
void test7()
{for (int i = 0; i < 5; i++){std::unique_lock<std::mutex> l(mu);std::cout << "test7 i = " << i << std::endl;cv.notify_one();print = true;}
}
void test8()
{for (int j = 0; j < 5; j++){std::unique_lock<std::mutex> l(mu);if (!print){cv.wait(l);}std::cout << "test8 j = " << j << std::endl;print = false;}
}CRITICAL_SECTION section;//临界区变量
void test01()
{for (int i = 0; i < 5; i++){EnterCriticalSection(&section);//类似于 mutex.lock() std::cout << "this is test01 i = " << i << std::endl;Sleep(1);LeaveCriticalSection(&section);//类似于 mutex.unlock() }
}
void test02()
{for (int j = 0; j < 5; j++){EnterCriticalSection(&section);std::cout << "this is test02 j = " << j << std::endl;Sleep(1);LeaveCriticalSection(&section);}
}
HANDLE hmutex;
void test03()
{for (int i = 0; i < 5; i++){WaitForSingleObject(hmutex, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 std::cout << "test03 i = " << i << std::endl;ReleaseMutex(hmutex);//类似于mutex.unlock() 释放互斥锁 }
}
void test04()
{for (int j = 0; j < 5; j++){WaitForSingleObject(hmutex, INFINITE);std::cout << "test04 j = " << j << std::endl;ReleaseMutex(hmutex);}
}
HANDLE hevent;
void test05()
{for (int i = 0; i < 5; i++){WaitForSingleObject(hevent, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 std::cout << "test05 i = " << i << std::endl;SetEvent(hevent);//类似于mutex.unlock() 释放互斥锁 }
}
void test06()
{for (int j = 0; j < 5; j++){WaitForSingleObject(hevent, INFINITE);std::cout << "test06 j = " << j << std::endl;SetEvent(hevent);}
}
HANDLE sem;
void test07()
{for (int i = 0; i < 5; i++){WaitForSingleObject(sem, INFINITE);//类似于mutex.lock() 阻塞等待多少时间 std::cout << "test07 i = " << i << std::endl;ReleaseSemaphore(sem, 1, NULL);//类似于mutex.unlock() 释放互斥锁 }
}
void test08()
{for (int j = 0; j < 5; j++){WaitForSingleObject(sem, INFINITE);std::cout << "test08 j = " << j << std::endl;ReleaseSemaphore(sem, 1, NULL);}
}int main(int argc, char const* argv[])
{int i = 0; int rtn = 0;int ret = 0;char buff[100];char *tmp = int2hex(82);//read_csv2();//ok//float num = 0.3;//int result = ceil(num);//printf("向上取整后的结果是:%d\n", result);--------------多线程-----START------------------------//f_multi_thread();//f_multiThread();//【Demo1】:创建一个最简单的线程//f_multiThread2();//【Demo2】:在线程函数中传入参数//f_multiThread3();//【Demo3】:线程同步//售票系统 ////Test2();//【Demo4】:模拟火车售票系统====== C++11 线程库 ==== START ==========//std::thread a;//创建线程1,定义线程,后面再分配任务//a = std::thread(threadProc);//std::thread b(threadProc2, 5);//创建线程2 ,定义线程的时候分配任务,参数类似于printf一样,可以为多个//a.join();//b.join();//采用join,主线程会阻塞等待子线程执行完毕//std::thread c(threadProc3);//c.detach();//采用detach,主线程不会等,这个线程开启早,还能输出到主线程的控制台//std::cout << "main thread exit" << std::endl;//std::thread d(threadProc4);//d.detach();////std::thread a(test1);//std::thread b(test2);//a.join();//b.join();//std::cout << "main thread finish." << std::endl;//std::thread a(test3);//std::thread b(test4);//a.join();//b.join();//std::cout << "main thread finish." << std::endl;//std::thread a(test5);//std::thread b(test6);//a.join();//b.join();//std::thread a(test7);//std::thread b(test8);//a.join();//b.join();====== C++11 线程库 ==== END ================== W32API实现线程同步 ==== START ==========//InitializeCriticalSection(&section);//初始化临界区对象//std::thread a(test01);//std::thread b(test02);//a.join();//b.join();//DeleteCriticalSection(&section);//用完了,就删除临界区 //hmutex = CreateMutex(NULL, FALSE, "mutex");//创建一个互斥锁 //std::thread a(test03);//std::thread b(test04);//a.join();//b.join();//CloseHandle(hmutex);//释放句柄 //hevent = CreateEvent(NULL, FALSE, TRUE, "event");//创建一个事件 //std::thread a(test05);//std::thread b(test06);//a.join();//b.join();//CloseHandle(hevent);//释放句柄 sem = CreateSemaphore(NULL, 1, 2, "semaphore");std::thread a(test07);std::thread b(test08);a.join();b.join();CloseHandle(sem);//释放句柄 ====== W32API实现线程同步 ==== END ============--------------多线程-----END--------------------------VS 与 Matlab 混合编程//rtn = f_VS_Matlab();system("pause");return 0;
}//售票程序
DWORD WINAPI SaleTicket(LPVOID lpParameter)
{THD_DATA* pThreadData = (THD_DATA*)lpParameter;TICKET* pSaleData = pThreadData->pTicket;while (pSaleData->nCount > 0){//请求获得一个互斥量锁WaitForSingleObject(g_hMutex2, INFINITE);if (pSaleData->nCount > 0){std::cout << pThreadData->strThreadName << "出售第" << pSaleData->nCount-- << "的票,";if (pSaleData->nCount >= 0) {std::cout << "出票成功!剩余" << pSaleData->nCount << "张票." << std::endl;}else {std::cout << "出票失败!该票已售完。" << std::endl;}}Sleep(10);//释放互斥量锁ReleaseMutex(g_hMutex2);}return 0L;
}
//售票系统
void Test2()
{//创建一个互斥量g_hMutex2 = CreateMutex(NULL, FALSE, NULL);//初始化火车票TICKET ticket;ticket.nCount = 100;strcpy(ticket.strTicketName, "北京-->赣州");const int THREAD_NUMM = 2;//8;//THD_DATA threadSale[THREAD_NUMM];HANDLE hThread[THREAD_NUMM];for (int i = 0; i < THREAD_NUMM; ++i){threadSale[i].pTicket = &ticket;std::string strThreadName = convertToString(i);strThreadName = "窗口" + strThreadName;strcpy(threadSale[i].strThreadName, strThreadName.c_str());//创建线程hThread[i] = CreateThread(NULL, NULL, SaleTicket, &threadSale[i], 0, NULL);//请求获得一个互斥量锁WaitForSingleObject(g_hMutex2, INFINITE);std::cout << threadSale[i].strThreadName << "开始出售 " << threadSale[i].pTicket->strTicketName << " 的票..." << std::endl;//释放互斥量锁ReleaseMutex(g_hMutex2);//关闭线程CloseHandle(hThread[i]);}system("pause");
}

参考:

【Linux】多线程同步的四种方式 - 西*风 - 博客园 (cnblogs.com)

一文搞定c++多线程同步机制_c++多线程同步等待-CSDN博客

C++多线程同步总结 - 念秋 - 博客园 (cnblogs.com)

Linux 下多线程(C语言) | 大眼睛男孩儿 (zhangxiaoya.github.io)

读写锁 - 张飘扬 - 博客园 (cnblogs.com)

Linux C++多线程同步的四种方式(非常详细)-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/24161.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI产品经理岗位需求量大吗?好找工作吗?

前言 在当今这个科技日新月异的时代&#xff0c;人工智能&#xff08;AI&#xff09;已不再仅仅是一个遥远的概念&#xff0c;而是深深嵌入到我们生活的方方面面&#xff0c;从日常的语音助手到复杂的自动驾驶系统&#xff0c;AI的触角无处不在。随着AI技术的广泛应用和持续进…

Docker搭建ELKF日志分析系统

Docker搭建ELKF日志分析系统 文章目录 Docker搭建ELKF日志分析系统资源列表基础环境一、系统环境准备1.1、创建所需的映射目录1.2、修改系统参数1.3、单击创建elk-kgc网络桥接 二、基于Dockerfile构建Elasticsearch镜像2.1、创建Elasticsearch工作目录2.2、上传资源到指定工作路…

python基础实例

下一个更大的数 定义一个Solution类&#xff0c;用于实现next_great方法 class Solution: def next_great(self, nums1, nums2): # 初始化一个空字典answer&#xff0c;用于存储答案 answer {} # 初始化一个空列表stack&#xff0c;用于存储待比较的数字 stack [] # 遍历nu…

短视频评论截取提取软件技术思路

关于开发短视频评论所需要用到得技术第一篇 前言&#xff1a;根据业务需要&#xff0c;我们需要通过短视频找到准客户&#xff0c;这个软件应该是叫短视频评论提取软件&#xff0c;或者是短视频评论采集。无所谓叫什么都可以 进入正题。 第一篇只讲解所应该用到得基础工作 一…

【Java】解决Java报错:ClassCastException

文章目录 引言1. 错误详解2. 常见的出错场景2.1 错误的类型转换2.2 泛型集合中的类型转换2.3 自定义类和接口转换 3. 解决方案3.1 使用 instanceof 检查类型3.2 使用泛型3.3 避免不必要的类型转换 4. 预防措施4.1 使用泛型和注解4.2 编写防御性代码4.3 使用注解和检查工具 5. 示…

springboot停车微信小程序小程序-计算机毕业设计源码92714

摘 要 在信息飞速发展的今天&#xff0c;网络已成为人们重要的信息交流平台。每天都有大量的农产品需要通过网络发布&#xff0c;为此&#xff0c;本人开发了一个基于springboot停车微信小程序小程序。 对于本停车微信小程序的设计来说&#xff0c;它主要是采用后台采用java语…

党史馆3d网上展馆

在数字化浪潮的推动下&#xff0c;华锐视点运用实时互动三维引擎技术&#xff0c;为用户带来前所未有的场景搭建体验。那就是领先于同行业的线上三维云展编辑平台搭建编辑器&#xff0c;具有零基础、低门槛、低成本等特点&#xff0c;让您轻松在数字化世界中搭建真实世界的仿真…

2.Rust自动生成文件解析

目录 一、生成目录解析二、生成文件解析2.1 Cargo.toml2.2 main函数解析 一、生成目录解析 先使用cargo clean命令删除所有生成的文件&#xff0c;下图显示了目录结构和 main.rs文件 使用cargo new testrust时自动创建出名为testrust的Rust项目。内部主要包含一个src的源码文…

Centos7安装ElasticSearch

Centos7安装ElasticSearch 准备工作 下载elasticsearch https://www.elastic.co/cn/elasticsearch 将下载好的包上传到/usr/local/elasticsearch/ 路径下 安装 安装elasticsearch解压缩即可&#xff01; tar -zxvf elasticsearch-8.12.2-linux-x86_64.tar.gz进入/usr/loca…

汽车EDI——Volvo EDI 项目案例

项目背景 作为Volvo的长期合作伙伴&#xff0c;C公司收到Volvo的EDI对接邀请&#xff0c;需要实现EDI对接。C公司将会面临哪些挑战&#xff1f;又应该相应地选择何种EDI解决方案呢&#xff1f; 汽车行业强调供需双方的高效协同&#xff08;比如研发设计、生产计划、物流信息等…

Hi3519DV500 学习摘录

文章目录 一、问题1、open-vm-tools 安装2、pushd: not found3、autoreconf4、编译util-linux源码时报错 ERROR: You must have autopoint installed to 二、NFS1、服务器搭建2、u-boot常用命令3、配置4、问题 三、补缺1、make 一、问题 1、open-vm-tools 安装 open-vm-tools…

关于使用XX源码,开始编译的时候报错:不允许使用返回函数的函数

在使用vlc源码&#xff0c;开始编译的时候遇到以下错误&#xff1a; 仔细一看&#xff0c;懵掉了&#xff0c;NND源码编译都有错&#xff1f;报错如下&#xff1a; 一顿查找后&#xff0c;得出解决问题的办法&#xff1a;把ssize_t改为int 在大多数情况下&#xff0c;你可以将…

國際知名榮譽顧問加入台灣分析集團總部,全面升級量子電腦Q系統

近期,國際知名的榮譽顧問正式加入台灣分析集團總部,利用相同的量子數據規格訊息數據庫,進行全方位的系統升級。此次升級後,量子電腦Q系統的精確預測和迅速反應能力提升了3.29%。透過高級的數據處理和技術分析,社群用戶將在瞬息萬變的市場中保持領先地位。 “量子電腦Q系統”由資…

使用紫铜管制作半波天线的折合振子

一、概述 半波天线是一种简单而有效的天线类型&#xff0c;其长度约为工作波长的一半。它具有较好的辐射特性和较高的增益&#xff0c;广泛应用于业余无线电、电视接收等领域。使用紫铜管制作折合振子&#xff0c;不仅可以提高天线的机械强度&#xff0c;还能增强其导电性能。 …

NSSCTF-Web题目7

目录 [SWPUCTF 2022 新生赛]ez_rce 1、题目 2、知识点 3、思路 ​编辑 [MoeCTF 2022]baby_file 1、题目 2、知识点 3、思路 [SWPUCTF 2022 新生赛]ez_rce 1、题目 2、知识点 ThinkPHP V5 框架漏洞的利用&#xff0c;命令执行 由于ThinkPHP5在处理控制器传参时&#xff…

经典神经网络(10)PixelCNN模型、Gated PixelCNN模型及其在MNIST数据集上的应用

经典神经网络(10)PixelCNN模型、Gated PixelCNN模型及其在MNIST数据集上的应用 1 PixelCNN PixelCNN是DeepMind团队在论文Pixel Recurrent Neural Networks (16.01)提出的一种生成模型&#xff0c;实际上这篇论文共提出了两种架构&#xff1a;PixelRNN和PixelCNN&#xff0c;两…

设计模式在芯片验证中的应用——迭代器

一、迭代器设计模式 迭代器设计模式(iterator)是一种行为设计模式&#xff0c; 让你能在不暴露集合底层表现形式 &#xff08;列表、 栈和树等数据结构&#xff09; 的情况下遍历集合中所有的元素。 在验证环境中的checker会收集各个monitor上送过来的transactions&#xff0…

设计软件有哪些?效果工具篇(2),渲染100邀请码1a12

这次我们继续介绍一些渲染效果和后期处理的工具。 1、Krakatoa Krakatoa是由Thinkbox Software开发的强大的粒子渲染器&#xff0c;可用于Autodesk 3ds Max等软件。它专注于处理大规模粒子数据&#xff0c;提供了高效的渲染解决方案&#xff0c;适用于各种特效、粒子系统和模…

TESSENT2024.1安装

一、安装过程参考Calibre安装过程&#xff08;此处省略&#xff0c;不再赘述&#xff09; 二、安装license管理器&#xff1a; SiemensLicenseServer_v2.2.1.0_Lnx64_x86-64.bin 三、Patch补丁&#xff1a; tessent安装目录和license管理安装目录&#xff0c;执行FlexNetLic…

企业必备技能导航栏的写法

创建一个导航栏是网页设计中的一个重要环节&#xff0c;它不仅有助于用户快速找到他们需要的信息&#xff0c;还能提升整个网站的用户体验。以下是一些基本步骤和技巧&#xff0c;可以帮助你快速制作一个高效且美观的导航栏&#xff1a; 确定导航栏位置&#xff1a;导航栏通常位…