线程同步

在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()


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值