wordpress添加样式表,sem优化软件选哪家,电子商务网站建设视频教学,河北汉佳 做网站的公司一、前言
线程是比进程更轻量级的执行单元#xff0c;允许在一个进程中并发执行多个控制流。每一个线程都有自己的程序计数器、寄存器集和栈空间#xff0c;但它们共享所属进程的全局数据和资源。这种共享内存模型使线程间的通信比进程间通信更为高效#xff0c;同时也带来…一、前言
线程是比进程更轻量级的执行单元允许在一个进程中并发执行多个控制流。每一个线程都有自己的程序计数器、寄存器集和栈空间但它们共享所属进程的全局数据和资源。这种共享内存模型使线程间的通信比进程间通信更为高效同时也带来了潜在的同步问题如死锁和竞态条件需要通过适当的同步机制来解决。
在程序设计中线程能够显著提高程序的响应速度和资源利用率特别是在处理CPU密集型或IO密集型任务时。例如一个图形用户界面GUI应用程序可以使用一个线程处理用户输入而另一个线程执行耗时的计算或网络请求这样可以避免UI冻结保持良好的用户体验。线程还常用于实现并行算法加快大数据处理、图像渲染等任务的执行速度。
在Windows环境下C语言可以通过调用Win32 API中的CreateThread函数来创建和管理线程。CreateThread函数允许你指定线程的入口点即线程函数、线程的优先级、堆栈大小等参数。 以下是一个使用CreateThread函数创建线程的简单示例
#include windows.h
#include stdio.h// 线程函数
DWORD WINAPI ThreadFunction(LPVOID lpParam)
{int id *(int *)lpParam;printf(Hello from thread %d\n, id);return 0;
}int main()
{HANDLE hThread;DWORD threadID;int threadParameter 1;// 创建线程hThread CreateThread(NULL, // 默认的安全属性0, // 使用默认堆栈大小ThreadFunction, // 线程函数threadParameter, // 传递给线程函数的参数0, // 创建标志0表示立即启动threadID); // 返回线程IDif (hThread NULL){printf(Error creating thread. Error code: %d\n, GetLastError());return 1;}// 等待线程结束WaitForSingleObject(hThread, INFINITE);// 关闭线程句柄CloseHandle(hThread);return 0;
}在这个示例中CreateThread函数接收多个参数包括一个线程函数指针、一个指向线程参数的指针、线程的创建标志等。当线程创建成功后CreateThread函数返回一个句柄这个句柄可以用于后续的线程控制操作如等待线程结束、终止线程或查询线程状态。
通过这种方式C语言程序员可以在Windows平台上利用多线程编程有效地提高程序性能和响应能力同时解决复杂的问题域。多线程编程同时也带来了同步和死锁等问题需要开发者采用合适的同步机制如互斥量、信号量、临界区等以确保线程安全和程序的正确性。 二、实操案例
2.1 CreateThread函数
CreateThread函数是Windows API中用于创建新线程的核心函数。在C或C语言中可以从一个现有的进程中启动一个新的执行流。
下面详细介绍了CreateThread函数的原型和每个参数的意义
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // 线程安全性属性SIZE_T dwStackSize, // 线程堆栈大小LPTHREAD_START_ROUTINE lpStartAddress, // 线程函数的入口点LPVOID lpParameter, // 传递给线程函数的参数DWORD dwCreationFlags, // 创建线程的标志LPDWORD lpThreadId // 输出参数接收线程ID
);lpThreadAttributes: 是一个指向SECURITY_ATTRIBUTES结构的指针用于指定线程的安全属性比如权限和安全描述符。如果你不需要特别的安全设置通常可以传递NULL。 dwStackSize: 是一个SIZE_T类型的值用来指定新线程的堆栈大小以字节为单位。如果设置为0则使用系统的默认堆栈大小。 lpStartAddress: 是一个LPTHREAD_START_ROUTINE类型的指针指向线程的起始函数。这是一个回调函数当线程开始执行时会被调用。这个函数的原型通常如下 DWORD WINAPI ThreadFunction(LPVOID lpParameter);其中lpParameter是在CreateThread调用中传递的参数。 lpParameter: 是一个LPVOID类型的指针可以用来向线程函数传递参数。这个参数会被直接传递给lpStartAddress所指向的函数。 dwCreationFlags: 是一个DWORD类型的值用于指定线程创建的标志。常见的标志包括 0: 立即开始执行线程。CREATE_SUSPENDED: 创建线程但不立即执行它。线程处于挂起状态可以通过ResumeThread函数恢复执行。 lpThreadId: 是一个指向DWORD类型的指针CreateThread成功创建线程后会将线程的唯一标识符ID写入这个指针所指向的位置。这个ID可以用于后续的线程管理和控制。
CreateThread函数的返回值是一个HANDLE类型的值这是新创建线程的句柄。这个句柄可以用于后续的线程控制操作比如WaitForSingleObject等待线程结束、TerminateThread终止线程或ResumeThread恢复挂起的线程。
一旦线程完成执行或被终止线程对象仍然存在直到CloseHandle函数被调用来释放它。因此在使用CreateThread创建线程后记得在适当的时候调用CloseHandle来清理资源。
2.2 案例1创建多个线程同时运行
开发环境在Windows下安装一个VS即可。我当前采用的版本是VS2020。
在C语言中使用多线程尤其是使用Windows API进行多线程编程涉及创建和管理多个线程来并发执行任务。
下面代码演示了如何在C语言中创建多个线程并让它们同时运行每个线程执行简单的打印操作。此代码将创建五个线程每个线程都会打印一条消息。
#include windows.h
#include stdio.h// 线程函数
DWORD WINAPI PrintMessage(LPVOID lpParam)
{int id (int)lpParam;printf(Hello from thread ID: %d\n, id);return 0;
}int main()
{HANDLE hThreads[5]; // 数组用于保存所有线程的句柄DWORD threadIDs[5]; // 数组用于保存所有线程的ID// 创建五个线程for (int i 0; i 5; i){hThreads[i] CreateThread(NULL, // 默认安全属性0, // 使用默认堆栈大小PrintMessage, // 线程函数(LPVOID)(i 1), // 传递给线程函数的参数0, // 创建标志0表示立即启动threadIDs[i]); // 返回线程IDif (hThreads[i] NULL){printf(Failed to create thread %d.\n, i);return 1;}}// 等待所有线程结束for (int i 0; i 5; i){WaitForSingleObject(hThreads[i], INFINITE);}// 关闭所有线程句柄for (int i 0; i 5; i){CloseHandle(hThreads[i]);}return 0;
}在这段代码中PrintMessage函数是每个线程将要执行的任务。它接收一个LPVOID类型的参数这个参数是在CreateThread函数中传递的。在这个例子中我们传递了一个整数i1作为参数这使得每个线程都有一个唯一的ID。
main函数中我们使用一个循环来创建五个线程。每个线程的句柄被存储在hThreads数组中而每个线程的ID则存储在threadIDs数组中。CreateThread函数的最后一个参数threadIDs[i]是一个指向数组元素的指针用于接收新创建线程的ID。
在所有线程创建完毕后再次使用一个循环来等待所有线程结束。WaitForSingleObject函数用于阻塞当前线程直到指定的线程结束。由于我们使用INFINITE作为超时值这意味着WaitForSingleObject将一直等待直到指定的线程确实结束。
最后使用另一个循环来关闭所有线程的句柄这是必要的资源清理步骤以避免资源泄漏。 2.3 案例2多线程处理并发处理网络请求
开发环境在Windows下安装一个VS即可。我当前采用的版本是VS2020。
创建一个使用子线程并发处理客户端连接的TCP服务器是一个典型的多线程编程场景。以下是一个使用C语言和Windows Socket APIWinsock的示例代码展示了如何创建一个TCP服务器该服务器在接收到客户端连接时为每个客户端创建一个子线程来处理通信。
以下是一个示例
#include winsock2.h
#include ws2tcpip.h
#include windows.h
#include stdio.h
#include string.h#pragma comment(lib, ws2_32.lib)#define SERVER_PORT 27015
#define BUFFER_SIZE 1024// 子线程函数用于处理客户端连接
DWORD WINAPI ClientHandler(LPVOID clientSocket)
{SOCKET sock (SOCKET)clientSocket;char buffer[BUFFER_SIZE];int bytesReceived;while ((bytesReceived recv(sock, buffer, BUFFER_SIZE, 0)) 0){buffer[bytesReceived] \0;printf(Received from client: %s\n, buffer);send(sock, buffer, bytesReceived, 0);}if (bytesReceived SOCKET_ERROR){printf(recv failed with error: %d\n, WSAGetLastError());}else if (bytesReceived 0){printf(Client disconnected\n);}closesocket(sock);return 0;
}int main(int argc, char* argv[])
{WSADATA wsaData;SOCKET serverSocket;struct addrinfo hints, *result, *ptr;int iResult;HANDLE hThread;// 初始化WinsockiResult WSAStartup(MAKEWORD(2, 2), wsaData);if (iResult ! 0){printf(WSAStartup failed: %d\n, iResult);return 1;}ZeroMemory(hints, sizeof(hints));hints.ai_family AF_UNSPEC;hints.ai_socktype SOCK_STREAM;hints.ai_protocol IPPROTO_TCP;hints.ai_flags AI_PASSIVE;// 解析服务器地址和端口iResult getaddrinfo(NULL, 27015, hints, result);if (iResult ! 0){printf(getaddrinfo failed: %d\n, iResult);WSACleanup();return 1;}// 创建服务器套接字ptr result;serverSocket socket(ptr-ai_family, ptr-ai_socktype, ptr-ai_protocol);if (serverSocket INVALID_SOCKET){printf(socket failed with error: %ld\n, WSAGetLastError());freeaddrinfo(result);WSACleanup();return 1;}// 绑定套接字iResult bind(serverSocket, ptr-ai_addr, (int)ptr-ai_addrlen);if (iResult SOCKET_ERROR){printf(bind failed with error: %d\n, WSAGetLastError());freeaddrinfo(result);closesocket(serverSocket);WSACleanup();return 1;}freeaddrinfo(result);// 开始监听iResult listen(serverSocket, SOMAXCONN);if (iResult SOCKET_ERROR){printf(listen failed with error: %d\n, WSAGetLastError());closesocket(serverSocket);WSACleanup();return 1;}printf(Server is ready to accept connections...\n);while (1){SOCKET clientSocket accept(serverSocket, NULL, NULL);if (clientSocket INVALID_SOCKET){printf(accept failed: %d\n, WSAGetLastError());break;}// 创建子线程来处理客户端连接hThread CreateThread(NULL, 0, ClientHandler, (LPVOID)clientSocket, 0, NULL);if (hThread NULL){printf(CreateThread failed with error: %d\n, GetLastError());closesocket(clientSocket);continue;}CloseHandle(hThread);}// 清理closesocket(serverSocket);WSACleanup();return 0;
}这段代码初始化Winsock创建一个监听特定端口的TCP服务器。每当有客户端连接时服务器就创建一个新的线程来处理该客户端的通信。在子线程中ClientHandler函数接收来自客户端的数据将其打印出来并将同样的数据回传给客户端。 由于CreateThread函数创建的线程默认是守护线程非前台线程因此主线程结束时子线程也将被终止。在上面的代码中CloseHandle函数被用来关闭线程句柄但这并不意味着线程立即结束它只是释放了主线程对线程句柄的引用。 文章转载自: http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.wlggr.cn.gov.cn.wlggr.cn http://www.morning.wcghr.cn.gov.cn.wcghr.cn http://www.morning.flqkp.cn.gov.cn.flqkp.cn http://www.morning.syxmx.cn.gov.cn.syxmx.cn http://www.morning.ydrml.cn.gov.cn.ydrml.cn http://www.morning.youyouling.cn.gov.cn.youyouling.cn http://www.morning.cykqb.cn.gov.cn.cykqb.cn http://www.morning.sxcwc.cn.gov.cn.sxcwc.cn http://www.morning.tlpgp.cn.gov.cn.tlpgp.cn http://www.morning.hyryq.cn.gov.cn.hyryq.cn http://www.morning.ejknty.cn.gov.cn.ejknty.cn http://www.morning.qtsks.cn.gov.cn.qtsks.cn http://www.morning.mywnk.cn.gov.cn.mywnk.cn http://www.morning.mnbcj.cn.gov.cn.mnbcj.cn http://www.morning.pjwrl.cn.gov.cn.pjwrl.cn http://www.morning.ptdzm.cn.gov.cn.ptdzm.cn http://www.morning.qwwcf.cn.gov.cn.qwwcf.cn http://www.morning.ghssm.cn.gov.cn.ghssm.cn http://www.morning.bmbnc.cn.gov.cn.bmbnc.cn http://www.morning.blzrj.cn.gov.cn.blzrj.cn http://www.morning.zrqs.cn.gov.cn.zrqs.cn http://www.morning.ntwfr.cn.gov.cn.ntwfr.cn http://www.morning.fdrwk.cn.gov.cn.fdrwk.cn http://www.morning.qnsmk.cn.gov.cn.qnsmk.cn http://www.morning.nfpkx.cn.gov.cn.nfpkx.cn http://www.morning.sgnjg.cn.gov.cn.sgnjg.cn http://www.morning.zkpwk.cn.gov.cn.zkpwk.cn http://www.morning.tyrlk.cn.gov.cn.tyrlk.cn http://www.morning.stsnf.cn.gov.cn.stsnf.cn http://www.morning.hpdpp.cn.gov.cn.hpdpp.cn http://www.morning.nhrkl.cn.gov.cn.nhrkl.cn http://www.morning.rkjb.cn.gov.cn.rkjb.cn http://www.morning.kwnbd.cn.gov.cn.kwnbd.cn http://www.morning.qdzqf.cn.gov.cn.qdzqf.cn http://www.morning.pqhfx.cn.gov.cn.pqhfx.cn http://www.morning.dmchips.com.gov.cn.dmchips.com http://www.morning.qtltg.cn.gov.cn.qtltg.cn http://www.morning.nckjk.cn.gov.cn.nckjk.cn http://www.morning.tkztx.cn.gov.cn.tkztx.cn http://www.morning.mdnnz.cn.gov.cn.mdnnz.cn http://www.morning.kqblk.cn.gov.cn.kqblk.cn http://www.morning.nzms.cn.gov.cn.nzms.cn http://www.morning.kchwr.cn.gov.cn.kchwr.cn http://www.morning.xsklp.cn.gov.cn.xsklp.cn http://www.morning.bmhc.cn.gov.cn.bmhc.cn http://www.morning.yfpnl.cn.gov.cn.yfpnl.cn http://www.morning.bscsp.cn.gov.cn.bscsp.cn http://www.morning.srbbh.cn.gov.cn.srbbh.cn http://www.morning.nqlx.cn.gov.cn.nqlx.cn http://www.morning.pmftz.cn.gov.cn.pmftz.cn http://www.morning.cfcdr.cn.gov.cn.cfcdr.cn http://www.morning.tqdlk.cn.gov.cn.tqdlk.cn http://www.morning.lsyk.cn.gov.cn.lsyk.cn http://www.morning.tslfz.cn.gov.cn.tslfz.cn http://www.morning.kdpal.cn.gov.cn.kdpal.cn http://www.morning.drzkk.cn.gov.cn.drzkk.cn http://www.morning.plqsz.cn.gov.cn.plqsz.cn http://www.morning.lgnz.cn.gov.cn.lgnz.cn http://www.morning.fylsz.cn.gov.cn.fylsz.cn http://www.morning.hlnys.cn.gov.cn.hlnys.cn http://www.morning.kndyz.cn.gov.cn.kndyz.cn http://www.morning.jxcwn.cn.gov.cn.jxcwn.cn http://www.morning.tnhqr.cn.gov.cn.tnhqr.cn http://www.morning.qclmz.cn.gov.cn.qclmz.cn http://www.morning.fpngg.cn.gov.cn.fpngg.cn http://www.morning.kphsp.cn.gov.cn.kphsp.cn http://www.morning.qjzgj.cn.gov.cn.qjzgj.cn http://www.morning.rxsgk.cn.gov.cn.rxsgk.cn http://www.morning.rkqqf.cn.gov.cn.rkqqf.cn http://www.morning.tqwcm.cn.gov.cn.tqwcm.cn http://www.morning.ckwxs.cn.gov.cn.ckwxs.cn http://www.morning.qhkdt.cn.gov.cn.qhkdt.cn http://www.morning.rbcw.cn.gov.cn.rbcw.cn http://www.morning.nfnxp.cn.gov.cn.nfnxp.cn http://www.morning.ckzjl.cn.gov.cn.ckzjl.cn http://www.morning.myhpj.cn.gov.cn.myhpj.cn http://www.morning.ksbmx.cn.gov.cn.ksbmx.cn http://www.morning.nba1on1.com.gov.cn.nba1on1.com http://www.morning.nhrkc.cn.gov.cn.nhrkc.cn