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(§ion);//类似于 mutex.lock() cout<<"this is test01 i = "<<i<<endl;Sleep(1);LeaveCriticalSection(§ion);//类似于 mutex.unlock() }
}
void test02()
{for(int j=0;j<5;j++){EnterCriticalSection(§ion);cout<<"this is test02 j = "<<j<<endl;Sleep(1);LeaveCriticalSection(§ion);}
}
int main()
{InitializeCriticalSection(§ion);//初始化临界区对象thread a(test01);thread b(test02);a.join();b.join();DeleteCriticalSection(§ion);//用完了,就删除临界区
}
运行结果:
效果类似于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(§ion);//类似于 mutex.lock() std::cout << "this is test01 i = " << i << std::endl;Sleep(1);LeaveCriticalSection(§ion);//类似于 mutex.unlock() }
}
void test02()
{for (int j = 0; j < 5; j++){EnterCriticalSection(§ion);std::cout << "this is test02 j = " << j << std::endl;Sleep(1);LeaveCriticalSection(§ion);}
}
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(§ion);//初始化临界区对象//std::thread a(test01);//std::thread b(test02);//a.join();//b.join();//DeleteCriticalSection(§ion);//用完了,就删除临界区 //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博客
相关文章:
C++多线程同步总结
C多线程同步总结 关于C多线程同步 一、C11规范下的线程库 1、C11 线程库的基本用法:创建线程、分离线程 #include<iostream> #include<thread> #include<windows.h> using namespace std; void threadProc() {cout<<"this is in t…...
【机器学习】基于CNN-RNN模型的验证码图片识别
1. 引言 1.1. OCR技术研究的背景 1.1.1. OCR技术能够提升互联网体验 随着互联网应用的广泛普及,用户在日常操作中频繁遇到需要输入验证码的场景,无论是在登录、注册、支付还是其他敏感操作中,验证码都扮演着重要角色来确保安全性。然而&am…...
一文读懂Samtec分离式线缆组件选型 | 快速攻略
【摘要/前言】 2023年,全球线缆组件市场规模大致在2100多亿美元。汽车和电信行业是线缆组件最大的两个市场,中国和北美是最大的两个制造地区。有趣的是,特定应用(即定制)和矩形组件是两个最大的产品组。 【Samtec产品…...
批量申请SSL证书如何做到既方便成本又最低
假如您手头拥有1千个域名,并且打算为每一个域名搭建网站,那么在当前的网络环境下,您必须确保这些网站通过https的方式提供服务。这意味着,您将为每一个域名申请SSL证书,以确保网站数据传输的安全性和可信度。那么&…...
Python 设计模式(创建型)
文章目录 抽象工厂模式场景示例 单例模式场景实现方式 工厂方法模式场景示例 简单工厂模式场景示例 建造者模式场景示例 原型模式场景示例 抽象工厂模式 抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,它提供了一种将一组相关…...
PyTorch 索引与切片-Tensor基本操作
以如下 tensor a 为例,展示常用的 indxing, slicing 及其他高阶操作 >>> a torch.rand(4,3,28,28) >>> a.shape torch.Size([4, 3, 28, 28])Indexing: 使用索引获取目标对象,[x,x,x,....] >>> a[0].shape torch.Size([3, 2…...
深入浅出 LangChain 与智能 Agent:构建下一代 AI 助手
我们小时候都玩过乐高积木。通过堆砌各种颜色和形状的积木,我们可以构建出城堡、飞机、甚至整个城市。现在,想象一下如果有一个数字世界的乐高,我们可以用这样的“积木”来构建智能程序,这些程序能够阅读、理解和撰写文本…...
scss是什么安装使⽤的步骤
当谈到SCSS时,我们首先需要了解它是什么。SCSS,也称为Sassy CSS,是Sass(Syntactically Awesome Stylesheets)的一种语法,它是CSS的预处理器,允许你使用变量、嵌套规则、混合(mixin&a…...
Pspark从hive读数据写到Pgsql数据库
前提条件 要使用PySpark从Hive读取数据并写入到PostgreSQL数据库,你需要确保以下几点: 你的PySpark环境已经配置好,并且能够连接到你的Hive数据。 PostgreSQL JDBC驱动程序已经添加到你的PySpark环境中。 你已经在PostgreSQL中创建好了相应…...
Pixi.js学习 (六)数组
目录 前言 一、数组 1.1 定义数组 1.2 数组存取与删除 1.3 使用数组统一操作敌机 二、实战 例题一:使用数组统一操作敌机 例题一代码: 总结 前言 为了提高作者的代码编辑水品,作者在使用博客的时候使用的集成工具为 HBuilderX。 下文所有截…...
操作系统复习-Linux的文件系统
文件系统概述 FAT FAT(File Allocation Table)FAT16、FAT32等,微软Dos/Windows使用的文件系统使用一张表保存盘块的信息 NTFS NTFS (New Technology File System)WindowsNT环境的文件系统NTFS对FAT进行了改进,取代了日的文件系统 EXT EXT(Extended…...
代码随想录算法训练营第三十六天| 860.柠檬水找零、 406.根据身高重建队列、 452. 用最少数量的箭引爆气球
LeetCode 860.柠檬水找零 题目链接:https://leetcode.cn/problems/lemonade-change/description/ 文章链接:https://programmercarl.com/0860.%E6%9F%A0%E6%AA%AC%E6%B0%B4%E6%89%BE%E9%9B%B6.html 思路 贪心算法:遇见20的时候有两种找零的…...
如何在C#中实现多线程
在C#中实现多线程有多种方式,包括使用System.Threading.Thread类、System.Threading.Tasks.Task类、System.Threading.Tasks.Parallel类以及异步编程模型(async和await)。下面我将为你展示每种方法的基本用法。 1. 使用System.Threading.Thread类 using System; using Syst…...
【LLM】快速了解Dify 0.6.10的核心功能:知识库检索、Agent创建和工作流编排(二)
【LLM】快速了解Dify 0.6.10的核心功能:知识库检索、Agent创建和工作流编排(二) 文章目录 【LLM】快速了解Dify 0.6.10的核心功能:知识库检索、Agent创建和工作流编排(二)一、创建一个简单的聊天助手&#…...
【介绍下Pandas,什么是Pandas?】
🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...
linux系统安装anaconda,并通过java程序调用python程序
虚拟环境准备 首先准备一块空的分区,安装anaconda至少要20g以上才能执行简单程序,这里准备20G的磁盘空间 创建分区,执行以下步骤,之后执行reboot重启 fdisk /dev/sda p n 回车 回车 w查看当前系统创建的分区,我这里是名为sda3的…...
Stable diffusion的SDXL模型,针不错!(含实操)
与之前的SD1.5大模型不同,这次的SDXL在架构上采用了“两步走”的生图方式: 以往SD1.5大模型,生成步骤为 Prompt → Base → Image,比较简单直接;而这次的SDXL大模型则是在中间加了一步 Refiner。Refiner的作用是什么呢…...
wordpress轻量免费主题
WordPress建站公司 适合提供WordPress建站服务的公司或个体(个人)工作室使用的WordPress建站公司主题模板。 https://www.jianzhanpress.com/?p545 首屏大图红色简洁wordpress主题 首屏大图红色简洁wordpress主题,非常地高端大气上档次,可用于多个行…...
Go AfterFunc 不触发
前言 函数原型为: func AfterFunc(d Duration, f func()) *TimerGo 的 time.AfterFunc 的作用是等待指定的时间间隔,然后在它自己的 goroutine 中调用 f。 现在有一个问题,我明明调用了 AfterFunc,但是它还没调用我指定的函数&…...
小程序视图渲染数据和部分事件的绑定
今天依旧使用这个目录进行教学 数据的渲染 在 index.js的 page中定义一个data对象结构是这样的 Page({data:{name:张三} }) 在index.wxml 中 利用模板语法进行渲染 <view >{{name}}</view> 注意这个模板里边不能使用js的方法 要循环渲染数组,如 在…...
“探索AIGC市场:腾讯元宝APP加入竞争,大模型产品的未来走向与个人选择“
文章目录 每日一句正能量前言使用体验分享独特优势和倾向选择字节豆包百度文心一言阿里通义千问腾讯元宝个人倾向选择结论 未来发展方向技术创新可持续可拓展性用户体验应用场景政府赋能数据安全与隐私保护伦理与社会责任国际合作与竞争结论 后记 每日一句正能量 不管现在有多么…...
node设置镜像源详细教程
在Node.js环境中,你可以通过设置npm或yarn的镜像源来加速依赖包的下载。以下是如何设置npm和yarn的镜像源的详细步骤: 使用npm设置镜像源 临时设置镜像源: 你可以在安装包时临时指定镜像源,例如: npm install package…...
四季变换,制氮机使用注意事项
随着四季的轮回变换,大自然展现着不同的风貌。对于制氮机而言,季节的变换同样会带来不同的使用挑战和注意事项。本文将为您揭示四季变换对制氮机使用的影响,帮助您更好地掌握制氮机的季节使用须知。 春季 温湿度变化:春季温湿度逐…...
如何实现办公终端安全
在网络安全日益严峻的当下,可信白名单作为一种高效的终端安全防护手段,正在逐渐受到业界的广泛关注和应用。本文将简要探讨可信白名单如何实现终端安全的原理、方法及其在实际应用中的优势与挑战。 首先,我们需要了解可信白名单的基本原理。可…...
【云岚到家】-day01-项目熟悉-查询区域服务开发
文章目录 1 云岚家政项目概述1.1 简介1.2 项目业务流程1.3 项目业务模块1.4 项目架构及技术栈1.5 学习后掌握能力 2 熟悉项目2.1 熟悉需求2.2 熟悉设计2.2.1 表结构2.2.2 熟悉工程结构2.2.3 jzo2o-foundations2.2.3.1 工程结构2.2.3.2 接口测试 3 开发区域服务模块3.1 流程分析…...
Docker面试整理-如何进行Docker镜像的构建和发布?
构建和发布 Docker 镜像是 Docker 使用中的一个常见任务,通常涉及编写 Dockerfile、构建镜像以及将其推送到镜像仓库的过程。以下是构建和发布 Docker 镜像的详细步骤: 1. 编写 Dockerfile 首先,你需要创建一个 Dockerfile,这是一个包含了一系列指令的文本文件,用来告诉 D…...
macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载)
macOS Sequoia 将 Mac 生产力与智能化提升至全新高度 (macOS 15 ISO、IPSW、PKG 下载) iPhone 镜像、Safari 浏览器重大更新、备受瞩目的游戏和 Apple Intelligence 等众多全新功能令 Mac 使用体验再升级 请访问原文链接:https://sysin.org/blog/macOS-Sequoia/&a…...
用户管理与服务器远程管理
用户管理 服务器系统版本介绍 windows服务器系统:win2000 win2003 win2008 win2012 linux服务器系统:Redhat Centos 用户管理 用户概述 (1)每一个用户登录系统后,拥有不同的操作权限。 (2)…...
Pytorch 实现简单的 线性回归 算法
Pytorch实现简单的线性回归算法 简单 tensor的运算 Pytorch涉及的基本数据类型是tensor(张量)和Autograd(自动微分变量) import torch x torch.rand(5, 3) #产生一个5*3的tensor,在 [0,1) 之间随机取值 y torch.o…...
Django中配置日志
在Django中配置日志的方法非常简单,只需要在 setting 文件中添加配置项,系统会自动生成相应的日志文件,也可以配置调试时显示内容,报错发送邮件等操作。 在setting.py中添加以下配置。 # 日志配置 LOGS_DIRS os.path.join(BASE…...
昆明网上房地产官网/百度惠生活怎么优化排名
0x01 起因及想法 起因:好久没更新博客了,我在乌云社区看到一篇代码审计的整体学习思想如下: 学习代码审计目标:能独立完成对一个CMS代码安全的监测 思路: A、通读全文代码,从功能函数代码开始阅读,例如incl…...
品牌网站建设相关问题/百度权重10的网站
前言:Wire.h是Arduino的IIC库。 一、Wire库函数 Wire.begin()Wire.requestFrom()Wire.beginTransmission()Wire.endTransmission()Wire.write()Wire.available()Wire.read()Wire.onReceive()Wire.onRequest()二、库函数详细介绍 1、Wire.begin() 和 Wire.begin(addr…...
公司注册网站诈骗莫名被起诉/友情链接只有链接
在对一个简单的Hello World工程进行项目结构剖析后,我们接着来学习下一个Android应用程序的生命周期是怎么样的,以便为后面的开发有个垫下良好的基石~ 所谓的应用程序生命周期无非就是应用程序进程从创建到消亡的整个过程。但是,之所有将这一…...
郎溪网站建设/人民网疫情最新消息
今天在安装zblog的时候出现了提示“release.xml不存在!”导致无法正常安装的问题: 解决后发篇文章分享下,如果遇到同样问题可以尝试按照本文操作下。 先说解决办法: 重新去zblog官方下载最新版的安装程序重新上传安装即可解决。 问题原因…...
山西正规网站建设报价公司/郑州百度推广托管
1. 背景 最近在研究DotNetOpenAuth——OAuth的一个.NET开源实现,官方网站:http://dotnetopenauth.net/ 。 从GitHub签出DotNetOpenAuth的源代码发现最新版本已到5.1,而NuGet中发布的版本只是4.3。新版中使用到了.NET 4.5的异步特性࿰…...
ps网页版在线制作/家庭优化大师
引用:http://www.williamlong.info/archives/3181.html CC攻击(Challenge Collapsar)是DDOS(分布式拒绝服务)的一种,也是一种常见的网站攻击方法,攻击者通过代理服务器或者肉鸡向向受害主机不停…...