线程的同步和互斥
1. 什么是同步,什么是互斥?
同步:线程同步并不是说线程同时运行,而是让线程按照一定的顺序执行,使得最后的数据能达到同步,多线程的情况下,如果不加以控制,多个线程一起对数据进行添加或者是修改,数据会异常混论。
互斥:有一些资源,比如:打印机。一次只能被一个线程访问,不允许多个线程同时访问,这种资源叫做临界资源。因此一个线程在访问这种资源的时候,其它线程不能访问,这就叫做互斥。【临界区:访问临界资源的那一段代码就叫做临界区。线程只有先进入临界区的才能访问到临界资源。】
2. 操作系统实现同步的方式
使用互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。比如Java中的synchronized关键词和各种Lock都是这种机制。
使用信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
3. c++ 实现互斥两种方式
提示
MyThread1 MyThread2 作为两个互斥进程 争抢屏幕输出
终端控制台作为 临界资源 一次只允许一个进程进行输出,不然屏幕输出会变得混乱
1. lock unlock实现互斥
#include <iostream>
#include <windows.h>
using namespace std;
HANDLE Semaphore;//声明
DWORD WINAPI MyThread1(LPVOID lpParamter)
{
while (1)
{
WaitForSingleObject(Semaphore, INFINITE);//lock
cout<<"Hello ";Sleep(1);
cout<<"world! ";Sleep(1);
cout<<endl;
ReleaseMutex(Semaphore);//unlock
}
}
DWORD WINAPI MyThread2(LPVOID lpParamter)
{
while (1)
{
WaitForSingleObject(Semaphore, INFINITE);//lock
cout<<"How ";Sleep(1);
cout<<"are ";Sleep(1);
cout<<"you! ";Sleep(1);
cout<<endl;
ReleaseMutex(Semaphore);//unlock
}
}
int main()
{
Semaphore = CreateMutex(NULL, FALSE, "screen");//创建互斥锁
//创建子线程
CreateThread(NULL, 0, MyThread1, NULL, 0, NULL);
CreateThread(NULL, 0, MyThread2, NULL, 0, NULL);
Sleep(500); //线程执行时间
return 0;
}
2. PV操作实现互斥
#include <windows.h>
#include <stdio.h>
#include <iostream>
#include "conio.h"
using namespace std;
HANDLE Semaphore; //声明信号量
DWORD WINAPI MyThread1(PVOID pvParam)
{
WaitForSingleObject(Semaphore,INFINITE); //p(Semaphore)
cout<<"Hello ";
//Sleep(1);
cout<<"world! ";
//Sleep(1);
cout<<endl;
ReleaseSemaphore(Semaphore,1,NULL); //v(Semaphore)
return 0;
}
DWORD WINAPI MyThread2(PVOID pvParam)
{
WaitForSingleObject(Semaphore,INFINITE); //p(Semaphore)
cout<<"How ";
//Sleep(1);
cout<<"are ";
//Sleep(1);
cout<<"you! ";
//Sleep(1);
cout<<endl;
ReleaseSemaphore(Semaphore,1,NULL); //v(Semaphore)
return 0;
}
int main()
{
Semaphore=CreateSemaphore(NULL,1,1,NULL); //信号灯初始化为1,第二个参数为初始值,第三个为最大值
//创建子线程
CreateThread(NULL, 0, MyThread1, NULL, 0, NULL);
CreateThread(NULL, 0, MyThread2, NULL, 0, NULL);
Sleep(100); //主线程等待
return 0;
}