机关单位网站建设合同,轴承外贸平台哪个网站最好,手机编辑html的工具,北京网站设计与网站制作Linux和windows进程同步与线程同步那些事儿#xff08;一#xff09; Linux和windows进程同步与线程同步那些事儿#xff08;二#xff09;#xff1a; windows线程同步详解示例 Linux和windows进程同步与线程同步那些事儿#xff08;三#xff09;#xff1a; Linux线…Linux和windows进程同步与线程同步那些事儿一 Linux和windows进程同步与线程同步那些事儿二 windows线程同步详解示例 Linux和windows进程同步与线程同步那些事儿三 Linux线程同步详解示例 Linux和windows进程同步与线程同步那些事儿四windows 下进程同步 Linux和windows进程同步与线程同步那些事儿五Linux下进程同步 1. 互斥量Mutex
互斥量是最常用的线程同步机制它可以确保在同一时间只有一个线程可以访问共享资源。 在Windows中可以使用CreateMutex函数来创建互斥量。
下面是一个使用互斥量实现进程同步的代码示例。该示例展示了两个进程之间如何使用互斥量来保证共享资源的互斥访问。
#include iostream
#include windows.hint main() {// 创建互斥量对象HANDLE hMutex CreateMutex(NULL, FALSE, MyMutex);if (hMutex NULL) {std::cout 互斥量创建失败 std::endl;return 1;}// 尝试获取互斥量的所有权DWORD dwWaitResult WaitForSingleObject(hMutex, INFINITE);if (dwWaitResult WAIT_OBJECT_0) {std::cout 进程A获得了互斥量的所有权 std::endl;// 模拟共享资源的访问std::cout 进程A正在访问共享资源... std::endl;Sleep(5000);// 释放互斥量的所有权ReleaseMutex(hMutex);std::cout 进程A释放了互斥量的所有权 std::endl;}else {std::cout 进程A无法获取互斥量的所有权 std::endl;}// 关闭互斥量句柄CloseHandle(hMutex);return 0;
}#include iostream
#include windows.hint main() {// 创建互斥量对象HANDLE hMutex CreateMutex(NULL, FALSE, MyMutex);if (hMutex NULL) {std::cout 互斥量创建失败 std::endl;return 1;}// 尝试获取互斥量的所有权DWORD dwWaitResult WaitForSingleObject(hMutex, INFINITE);if (dwWaitResult WAIT_OBJECT_0) {std::cout 进程B获得了互斥量的所有权 std::endl;// 模拟共享资源的访问std::cout 进程B正在访问共享资源... std::endl;Sleep(3000);// 释放互斥量的所有权ReleaseMutex(hMutex);std::cout 进程B释放了互斥量的所有权 std::endl;}else {std::cout 进程B无法获取互斥量的所有权 std::endl;}// 关闭互斥量句柄CloseHandle(hMutex);return 0;
}在上面的代码示例中进程A和进程B都通过调用CreateMutex函数来创建了一个名为MyMutex的互斥量对象。接着它们分别调用WaitForSingleObject函数来尝试获取互斥量的所有权。
如果某个进程成功获取了互斥量的所有权即dwWaitResult的值为WAIT_OBJECT_0那么它就可以访问共享资源。在示例中为了模拟共享资源的访问我们使用了Sleep函数来暂停程序的执行。
完成对共享资源的访问后进程需要调用ReleaseMutex函数来释放互斥量的所有权以便其他进程可以获取互斥量的所有权。
最后进程要调用CloseHandle函数来关闭互斥量句柄释放系统资源。
请注意这只是一个简单的示例实际的应用中可能还需要处理异常情况、错误处理等。 2. 事件Event
事件用于线程间的通信和同步允许线程等待某个特定事件的发生。 在Windows中可以使用CreateEvent函数来创建事件对象。
下面是一个使用事件(Event)实现进程同步的代码示例。该示例展示了两个进程之间如何使用事件来进行进程同步。
#include iostream
#include windows.hint main() {// 创建事件对象HANDLE hEvent CreateEvent(NULL, FALSE, FALSE, MyEvent);if (hEvent NULL) {std::cout 事件创建失败 std::endl;return 1;}// 等待事件变为有信号状态DWORD dwWaitResult WaitForSingleObject(hEvent, INFINITE);if (dwWaitResult WAIT_OBJECT_0) {std::cout 进程A检测到事件有信号 std::endl;// 执行需要同步的操作std::cout 进程A正在执行同步操作... std::endl;Sleep(5000);std::cout 进程A完成同步操作 std::endl;}else {std::cout 进程A等待事件超时或发生其他错误 std::endl;}// 关闭事件句柄CloseHandle(hEvent);return 0;
}#include iostream
#include windows.hint main() {// 打开事件对象HANDLE hEvent OpenEvent(EVENT_MODIFY_STATE, FALSE, MyEvent);if (hEvent NULL) {std::cout 事件打开失败 std::endl;return 1;}// 设置事件为有信号状态if (SetEvent(hEvent)) {std::cout 进程B设置了事件的信号 std::endl;}else {std::cout 进程B设置事件的信号失败 std::endl;}// 关闭事件句柄CloseHandle(hEvent);return 0;
}在上面的代码示例中进程A通过调用CreateEvent函数来创建了一个名为MyEvent的事件对象。而进程B则通过调用OpenEvent函数来打开同一个事件对象。
进程A调用WaitForSingleObject函数来等待事件变为有信号状态。一旦事件有信号进程A就可以执行需要同步的操作。在示例中我们使用了Sleep函数来模拟同步操作的执行。
进程B在需要进行同步的时候调用SetEvent函数来设置事件的信号。这样进程A就会被唤醒继续执行同步操作。
请注意事件对象具有自动复位auto-reset的特性即一旦某个等待事件的进程被唤醒事件会自动重置为无信号状态其他等待事件的进程将继续等待。
最后进程要调用CloseHandle函数来关闭事件句柄释放系统资源。 3. 临界区Critical Section
临界区用于保护共享资源确保在同一时间只有一个线程可以访问。 在Windows中可以使用InitializeCriticalSection函数来初始化临界区。
下面是一个使用临界区(Critical Section)实现进程同步的代码示例。该示例展示了两个进程之间如何使用临界区来进行进程同步。
#include iostream
#include windows.hCRITICAL_SECTION g_cs; // 全局临界区对象int main() {// 初始化临界区InitializeCriticalSection(g_cs);// 进入临界区EnterCriticalSection(g_cs);std::cout 进程A进入临界区执行同步操作... std::endl;Sleep(5000); // 模拟同步操作std::cout 进程A完成同步操作退出临界区 std::endl;// 离开临界区LeaveCriticalSection(g_cs);// 销毁临界区DeleteCriticalSection(g_cs);return 0;
}#include iostream
#include windows.hCRITICAL_SECTION g_cs; // 全局临界区对象int main() {// 初始化临界区InitializeCriticalSection(g_cs);// 进入临界区EnterCriticalSection(g_cs);std::cout 进程B进入临界区执行同步操作... std::endl;Sleep(5000); // 模拟同步操作std::cout 进程B完成同步操作退出临界区 std::endl;// 离开临界区LeaveCriticalSection(g_cs);// 销毁临界区DeleteCriticalSection(g_cs);return 0;
}在上面的代码示例中我们使用CRITICAL_SECTION类型的全局变量g_cs作为临界区对象。
进程A和进程B都会初始化临界区对象进入临界区进行同步操作。
在示例中我们使用了Sleep函数来模拟同步操作的执行。
进程A和进程B在完成同步操作后都需要离开临界区。
最后进程要调用DeleteCriticalSection函数来销毁临界区对象释放系统资源。
请注意临界区是进程内的同步机制不适用于跨进程的同步。如果需要跨进程的同步可以考虑使用互斥量(Mutex)或事件(Event)等其他机制。 4. 信号量Semaphore
信号量是一种经典的线程同步机制它可以用于控制对共享资源的访问。 在Windows中可以使用CreateSemaphore函数来创建信号量。
下面是一个使用信号量(Semaphore)实现进程同步的代码示例。该示例展示了两个进程之间如何使用信号量来进行进程同步。
#include iostream
#include windows.hHANDLE g_semaphore; // 全局信号量句柄int main() {// 创建一个信号量初始值为0用于进程同步g_semaphore CreateSemaphore(NULL, 0, 1, LProcessSync);std::cout 进程A执行同步操作... std::endl;Sleep(5000); // 模拟同步操作std::cout 进程A完成同步操作释放信号量 std::endl;ReleaseSemaphore(g_semaphore, 1, NULL); // 释放信号量允许进程B执行// 关闭信号量句柄CloseHandle(g_semaphore);return 0;
}#include iostream
#include windows.hHANDLE g_semaphore; // 全局信号量句柄int main() {// 创建一个信号量初始值为0用于进程同步g_semaphore CreateSemaphore(NULL, 0, 1, LProcessSync);// 进程B等待信号量直到进程A释放信号量WaitForSingleObject(g_semaphore, INFINITE);std::cout 进程B执行同步操作... std::endl;Sleep(5000); // 模拟同步操作std::cout 进程B完成同步操作释放信号量 std::endl;ReleaseSemaphore(g_semaphore, 1, NULL); // 释放信号量允许其他进程执行// 关闭信号量句柄CloseHandle(g_semaphore);return 0;
}在上面的示例代码中我们使用了HANDLE类型的全局变量g_semaphore作为信号量句柄。 进程A创建了一个名为ProcessSync的信号量并执行同步操作之后调用ReleaseSemaphore函数释放信号量。
进程B在等待信号量状态下调用WaitForSingleObject函数等待进程A释放信号量然后执行同步操作。 最后进程要调用CloseHandle函数来关闭信号量句柄释放系统资源。
请注意信号量是一种用于进程间同步的机制可以在不同进程之间实现同步。在示例中我们使用了一个简单的二进制信号量它的初始值为0进程A通过ReleaseSemaphore函数将其值设置为1使进程B可以继续执行。 5. 命名管道Named Pipe
命名管道是一种进程间通信的机制可以用于实现进程间的数据交换和同步。 在Windows中可以使用CreateNamedPipe函数来创建命名管道。
在 Windows 下可以使用命名管道Named Pipe实现多进程间的同步。命名管道是一种特殊的文件用于在不同进程间进行通信。下面是一个使用命名管道实现多进程同步的 C 代码示例
进程A写入数据
#include iostream
#include windows.hint main()
{HANDLE hPipe;// 创建命名管道LPCWSTR pipeName TEXT(\\\\.\\pipe\\my_pipe);hPipe CreateNamedPipe(pipeName,PIPE_ACCESS_DUPLEX,PIPE_TYPE_MESSAGE | PIPE_WAIT,1, // 最大实例数65536, // 输出缓冲区大小65536, // 输入缓冲区大小0, // 默认超时时间NULL // 安全属性);// 等待进程B连接ConnectNamedPipe(hPipe, NULL);// 向管道写入数据const char* data Hello, World!;DWORD bytesWritten;WriteFile(hPipe, data, strlen(data) 1, bytesWritten, NULL);// 关闭管道DisconnectNamedPipe(hPipe);CloseHandle(hPipe);return 0;
}进程B读取数据
#include iostream
#include windows.hint main()
{HANDLE hPipe;// 连接到命名管道LPCWSTR pipeName TEXT(\\\\.\\pipe\\my_pipe);hPipe CreateFile(pipeName,GENERIC_READ,0, // 共享模式NULL, // 安全属性OPEN_EXISTING,0, // 属性和标志NULL // 模板文件);// 从管道读取数据char buffer[65536];DWORD bytesRead;ReadFile(hPipe, buffer, sizeof(buffer), bytesRead, NULL);// 打印数据std::cout buffer std::endl;// 关闭管道CloseHandle(hPipe);return 0;
}上述代码中进程A创建了一个命名管道并等待进程B连接。然后它向管道写入数据。进程B连接到同一个命名管道并读取进程A写入的数据。
让我们更详细地解释一下代码 在进程A中CreateNamedPipe 函数用于创建命名管道。参数 pipeName 指定了命名管道的名称格式为 \\.\pipe\pipeName。其他参数设置了管道的访问权限、缓冲区大小等。 进程A调用 ConnectNamedPipe 函数等待进程B连接。 进程A使用 WriteFile 函数向管道写入数据。 进程B使用 CreateFile 函数连接到命名管道。 进程B调用 ReadFile 函数从管道中读取数据。 最后进程B关闭了管道。
在实际使用中可以根据需要对代码进行修改和扩展以满足你的具体需求。例如你可以使用多线程创建多个进程或者通过命名管道进行双向通信。 6. 共享内存Shared Memory
共享内存允许多个进程访问同一块内存区域从而实现进程间的数据共享和通信。 在Windows中可以使用CreateFileMapping和MapViewOfFile等函数来创建和访问共享内存区域。
下面是一个使用共享内存在Windows下实现多个进程同步的代码示例
#include iostream
#include Windows.h// 共享内存结构体
struct SharedData {HANDLE mutex; // 互斥量HANDLE event; // 事件CONDITION_VARIABLE conditionVariable; // 条件变量int counter; // 共享计数器
};int main() {// 创建共享内存HANDLE hMapFile CreateFileMapping(INVALID_HANDLE_VALUE,nullptr,PAGE_READWRITE,0,sizeof(SharedData),LMySharedMemory);if (hMapFile NULL) {std::cerr Failed to create shared memory std::endl;return 1;}// 获取共享内存指针SharedData* sharedData (SharedData*)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(SharedData));if (sharedData NULL) {std::cerr Failed to map shared memory std::endl;CloseHandle(hMapFile);return 1;}// 初始化互斥量、事件和条件变量sharedData-mutex CreateMutex(nullptr, FALSE, nullptr);sharedData-event CreateEvent(nullptr, FALSE, FALSE, nullptr);InitializeConditionVariable(sharedData-conditionVariable);sharedData-counter 0;// 创建多个进程进行同步操作for (int i 0; i 5; i) {STARTUPINFO si {};PROCESS_INFORMATION pi {};wchar_t cmdLine[] LChildProcess.exe; // 子进程程序名// 启动子进程if (!CreateProcess(nullptr,cmdLine,nullptr,nullptr,FALSE,0,nullptr,nullptr,si,pi)) {std::cerr Failed to create child process std::endl;CloseHandle(hMapFile);return 1;}// 关闭子进程句柄CloseHandle(pi.hThread);CloseHandle(pi.hProcess);}// 等待所有子进程执行完毕WaitForMultipleObjects(5, sharedData-processHandles, TRUE, INFINITE);// 输出计数器值std::cout Counter sharedData-counter std::endl;// 释放资源UnmapViewOfFile(sharedData);CloseHandle(sharedData-mutex);CloseHandle(sharedData-event);CloseHandle(hMapFile);return 0;
}这个示例中首先创建了一个共享内存来存储互斥量、事件和条件变量等同步对象以及一个共享计数器。然后创建了多个子进程在子进程中进行同步操作。
子进程代码示例ChildProcess.exe
#include iostream
#include Windows.hstruct SharedData {HANDLE mutex;HANDLE event;CONDITION_VARIABLE conditionVariable;int counter;
};int main() {HANDLE hMapFile OpenFileMapping(FILE_MAP_ALL_ACCESS,FALSE,LMySharedMemory);if (hMapFile NULL) {std::cerr Failed to open shared memory std::endl;return 1;}SharedData* sharedData (SharedData*)MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,sizeof(SharedData));if (sharedData NULL) {std::cerr Failed to map shared memory std::endl;CloseHandle(hMapFile);return 1;}// 等待主进程通知WaitForSingleObject(sharedData-event, INFINITE);// 互斥量保护临界区WaitForSingleObject(sharedData-mutex, INFINITE);// 执行同步操作sharedData-counter;std::cout Child process counter sharedData-counter std::endl;// 离开临界区ReleaseMutex(sharedData-mutex);// 通知主进程完成WakeConditionVariable(sharedData-conditionVariable);// 释放资源UnmapViewOfFile(sharedData);CloseHandle(hMapFile);return 0;
}在子进程中首先打开共享内存并获取共享内存指针。然后等待主进程通知获取互斥量保护临界区执行同步操作离开临界区通知主进程完成并释放资源。 总结
互斥量mutex 适用场景多个进程需要争夺同一个资源时只能有一个进程访问资源。 优点简单易用能够实现多个进程间的互斥访问。 缺点性能较低需要进行系统调用可能引起上下文切换开销。
事件event 适用场景多个进程需要等待某个特定事件的发生后才能继续执行。 优点可以在多个进程之间进行高效的同步。 缺点只能用于单个事件的同步不能用于争夺资源的同步。
临界区critical section 适用场景多个进程需要访问共享资源时只能有一个进程访问资源。 优点具有较高的性能适用于保护共享资源的场景。 缺点只能用于同一个进程内的进程同步不能用于跨进程同步。
信号量semaphore 适用场景多个进程需要访问有限数量的资源时控制同时访问的进程数量。 优点可以用于控制同时访问资源的进程数量。 缺点较复杂容易引发死锁问题。
命名管道named pipe 适用场景多个进程之间进行双向通信和同步。 优点提供了进程间的可靠通信和同步机制。 缺点性能较低只能用于进程之间的通信和同步。
共享内存shared memory 适用场景多个进程需要共享大块数据时。 优点高效的进程间通信能够实现数据共享。 缺点需要进行同步容易引发数据不一致或竞态条件。
综合比较
互斥量 : 适用于争夺单个资源的情况使用简单但性能较低。事件 : 适用于等待特定事件发生后才能继续执行的场景同步效率高。临界区: 适用于保护共享资源的场景性能较高。信号量: 适用于控制同时访问资源的进程数量但使用较复杂容易产生死锁。命名管道: 适用于进程间的通信和同步但性能较低。共享内存: 适用于共享大块数据的场景需要进行同步操作可能引发竞态条件。
根据具体的场景和需求可以选择合适的进程同步机制来实现进程间的同步和通信。