线程同步
在windows上,线程之间的同步有很多种方式,以下是利用事件对象实现同步的例子
#include <iostream>
#include <windows.h>
using namespace std;
HANDLE g_hEvent = NULL;
//
DWORD WINAPI ThreadProc1(LPVOID lpVoid)
{
if (!g_hEvent)
{
return 1;
}
if (WAIT_OBJECT_0 == WaitForSingleObject(g_hEvent, INFINITE))
{
for (int i = 0; i < 20; i++)
{
cout << "1 ";
}
cout << endl;
SetEvent(g_hEvent);
}
return 0;
}
//
DWORD WINAPI ThreadProc2(LPVOID lpVoid)
{
if (!g_hEvent)
{
return 1;
}
if (WAIT_OBJECT_0 == WaitForSingleObject(g_hEvent, INFINITE))
{
for (int i = 0; i < 20; i++)
{
cout << "2 ";
}
cout << endl;
SetEvent(g_hEvent);
}
return 0;
}
//
int main()
{
HANDLE hThread1 = CreateThread(NULL, 0, ThreadProc1, NULL, CREATE_SUSPENDED, NULL);
if (!hThread1)
{
cerr << "CreateThread1 error: " << GetLastError() << endl;
return 1;
}
HANDLE hThraed2 = CreateThread(NULL, 0, ThreadProc2, NULL, CREATE_SUSPENDED, NULL);
if (!hThraed2)
{
cerr << "CreateThread2 error: " << GetLastError() << endl;
return 1;
}
// 1、系统自动重置事件对象,这样,当g_hEvent为有信号时,只有一个线程能获得该对象,
// WaitForSingleObject函数得到执行允许时,会自动将g_hEvent设置为非信号状态
// 2、如果是人工重置的事件对象,当g_hEvent为有信号时,所有线程都能够同时执行(这就不能达到线程间同步啦)
// WaitForSingleObject函数得到执行允许时,不会将事件对象设置为非信号状态,如果此时调用SetEvent,
// 可能时间片已终止,线程切换,SetEvent等于没作用
g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // 创建系统自动重置对象
if (!g_hEvent)
{
cerr << "CreateEvent: " << GetLastError() << endl;
return 1;
}
ResumeThread(hThread1);
ResumeThread(hThraed2);
SetEvent(g_hEvent);
if (WAIT_OBJECT_0 == WaitForSingleObject(g_hEvent, INFINITE))
{
for (int i = 0; i < 20; i++)
{
cout << "3 ";
}
cout << endl;
SetEvent(g_hEvent);
}
CloseHandle(hThread1);
CloseHandle(hThraed2);
Sleep(10); // 让另外两个线程有时间执行完毕
CloseHandle(g_hEvent);
system("pause");
return 0;
}
事件对象不但可以做到线程间的同步,还可以做到进程间的同步,因为它是内核级的对象,是所有进程所共享的。
在linux上,线程之间的同步也是多种方式的,以下是利用互斥量实现同步的例子:
#include <iostream>
#include <pthread.h>
using namespace std;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; // 定义一个互斥量
void *ThreadProc1(void *pVoid)
{
pthread_mutex_lock(&g_mutex);
for (int i = 0; i < 20; i++)
{
cout << "1 ";
}
cout << endl;
pthread_mutex_unlock(&g_mutex);
}
void *ThreadProc2(void *pVoid)
{
pthread_mutex_lock(&g_mutex);
for (int i = 0; i < 20; i++)
{
cout << "2 ";
}
cout << endl;
pthread_mutex_unlock(&g_mutex);
}
int main()
{
pthread_t nTid1 = 0;
int nErr1 = pthread_create(&nTid1, NULL, ThreadProc1, NULL);
if (nErr1 != 0)
{
cerr << "thread1 create error: " << nErr1 << endl;
return 1;
}
pthread_t nTid2 = 0;
int nErr2 = pthread_create(&nTid2, NULL, ThreadProc2, NULL);
if (nErr2 != 0)
{
cerr << "thread2 create error: " << nErr2 << endl;
return 1;
}
pthread_mutex_lock(&g_mutex);
for (int i = 0; i < 20; i++)
{
cout << "3 ";
}
cout << endl;
pthread_mutex_unlock(&g_mutex);
sleep(1);
pthread_mutex_destroy(&g_mutex);
return 0;
}
可能有的朋友在执行上面的代码时发现,即使把互斥量去掉,程序也能正确的输出,是的,有可能,因为我们的执行时间比较短,线程的时间片足以支撑该线程进行输出操作,那么,上面的代码是否真正同步呢,有兴趣的朋友可以在每个输出的地方加个usleep(1)试下,就可以发现,确实是已经同步了哈。
顺便来看看python实现线程同步的方式,python实现同步的方式是lock,每次只有一个线程能得到这个锁,当一个线程释放的时候,其他线程会有一个能获得该锁,而不能获得的线程将继续等待。
import threading
from time import sleep
def Thread1():
lock.acquire()
for i in range(1, 20):
sleep(0.1)
print("1 ", end = '')
lock.release()
def Thread2():
lock.acquire()
for i in range(1, 20):
sleep(0.1)
print("2 ", end = '')
lock.release()
if __name__ == "__main__":
thread1 = threading.Thread(target = Thread1)
thread2 = threading.Thread(target = Thread2)
lock = threading.Lock()
thread1.start()
thread2.start()
lock.acquire()
for i in range(1, 20):
sleep(0.1)
print("3 ", end = '')
lock.release()
thread1.join()
thread2.join()