#if 0 //CreateThread代码示例
#include<iostream>
#include<windows.h>
using namespace std;
DWORD WINAPI ThreadFun(LPVOID lpThreadParameter)
{
char* str = (char*)lpThreadParameter;
while (true)
{
cout << "线程处理函数中接收到的参数是:" << str << endl;
cout << "子线程ID: " << GetCurrentThreadId() << endl;
Sleep(1000);
}
return 0;
}
int main()
{
DWORD threadId = 0;
HANDLE hThread = CreateThread(
NULL, //设为NULL表示默认安全性
0, //如果设为0,那么默认将使用与调用该函数的线程相同的栈空间大小
ThreadFun,//线程处理函数,函数名就是函数指针
"hello thread!",//向线程函数传入的参数
0, //0表示创建后马上运行
&threadId);
if (hThread == NULL){
cout << "线程创建失败,ERROR CODE : " << GetLastError() << endl;
}
cout << "线程的句柄:" << hThread << endl;
cout << "子线程的ID:" << threadId << endl;
cout << "主线程的ID:" << GetCurrentThreadId() << endl;
//关闭线程句柄,引用计数-1,并没有结束线程
//CloseHandle(hThread);//表示以后不再引用句柄
getchar();
//挂起线程
SuspendThread(hThread);
getchar();
//恢复执行线程
ResumeThread(hThread);
getchar();
return 0;
}
#endif
#if 0//多线程间消息通讯
#include<iostream>
#include<windows.h>
#include<stdio.h>
//自定义消息必须自定义在用户消息以上的数值
#define MY_MSG WM_USER+1
bool flag = true;
DWORD WINAPI ThreadFun1(LPVOID param)
{
//接收第二个线程发来的消息
MSG msg;
#if 0 //GetMessage 如果有消息继续,否则阻塞
while (GetMessage(
&msg,//接收消息的线程ID
NULL,//取得消息的窗口的句柄,当为NULL时获取所属线程的消息
0, //指定被检索的最小消息值的整数
0 //指定被检索的最大消息值的整数
))
{
switch (msg.message){
case MY_MSG:
printf("收到消息:%d\n", (int)msg.wParam);
break;
//case WM_QUIT:
// printf("收到WM_QUIT消息,退出!\n");//因为WM_QUIT消息会让GetMessage返回false所以不会进人循环
// break;
}
}
printf("收到WM_QUIT消息,退出!\n");
#endif
#if 1 //PeekMessage的用法 不阻塞线程
while (flag)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){//得到消息返回非零,否则返回0值
switch (msg.message){
case MY_MSG:
printf("收到消息:%d\n", (int)msg.wParam);
break;
case WM_QUIT:
printf("收到QUIT消息,退出!\n");
flag = false;
break;
}
}
}
#endif
return 0;
}
DWORD WINAPI ThreadFun2(LPVOID param)
{
//给第一个线程发送消息
DWORD threadId = (DWORD)param;
int N = 1;
while (TRUE){
if (N <= 3){
PostThreadMessage(threadId, MY_MSG, (WPARAM)N++, NULL);
}
else{
PostThreadMessage(threadId, WM_QUIT, NULL, NULL);
break;
}
Sleep(1000);
}
return 0;
}
int main()
{
DWORD threadID = 0;
HANDLE hthread1 = CreateThread(NULL, 0, ThreadFun1, NULL, 0, &threadID);
HANDLE hthread2 = CreateThread(NULL, 0, ThreadFun2, (LPVOID)threadID, 0, NULL);
HANDLE hArr[] = { hthread1, hthread2 };
WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
//getchar();
system("pause");
return 0;
}
#endif
#if 0//静态TLS(线程本地存储变量)
#include<iostream>
#include<Windows.h>
#include<stdio.h>
//声明为静态TLS(线程本地存储变量)
__declspec(thread) int N = 0;//每个线程中的值互不影响
DWORD WINAPI ThreadFun1(LPVOID param){
char *name = reinterpret_cast<char *>(param);//()还不能少
while (TRUE){
printf("线程%s打印:%d\n", name, ++N);
Sleep(1000);
}
}
DWORD WINAPI ThreadFun2(LPVOID param){
char *name = reinterpret_cast<char *>(param);//()还不能少
while (TRUE){
printf("\t\t\t线程%s打印:%d\n", name, ++(++N));
Sleep(1000);
}
}
void main(){
HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, "thread1", 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun2, "thread2", 0, NULL);
HANDLE hArr[] = { hThread1, hThread2 };
WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
system("pause");
}
#endif
#if 0//动态TLS(Thread Local Storage)
#include<iostream>
#include<stdio.h>
#include<Windows.h>
DWORD WINAPI ThreadFun1(LPVOID param);
DWORD WINAPI THreadFun2(LPVOID param);
//动态TLS的索引
DWORD tlsIndex = 0;
int main()
{
tlsIndex = TlsAlloc();//返回索引
if (tlsIndex == TLS_OUT_OF_INDEXES){
printf("分配TLS索引失败!\n");
return 0;
}
//在主线程中设置一个值
TlsSetValue(tlsIndex, "main cpp");
char *pName = (char*)TlsGetValue(tlsIndex);
printf("主线程打印: %s\n", pName);
HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun1, "A", 0, NULL);
HANDLE hThread2 = CreateThread(NULL, 0, THreadFun2, "B", 0, NULL);
HANDLE hArr[] = { hThread1, hThread2 };
WaitForMultipleObjects(2, hArr, TRUE, INFINITE);//等待两个线程执行完毕
TlsFree(tlsIndex);
system("pause");
return 0;
}
DWORD WINAPI ThreadFun1(LPVOID param){
TlsSetValue(tlsIndex, "hello");
while (true)
{
char *p = (char*)TlsGetValue(tlsIndex);
printf("线程A打印:%s\n", p);
Sleep(1000);
}
}
DWORD WINAPI THreadFun2(LPVOID param){
TlsSetValue(tlsIndex, "world");
while (true)
{
char *p = reinterpret_cast<char *>(TlsGetValue(tlsIndex));
printf("\t\t\t线程B打印:%s\n", p);
Sleep(1000);
}
}
#endif
#if 0//利用事件Event实现买票程序
#include<iostream>
#include<Windows.h>
#include<stdio.h>
#include<process.h>//_beginthread
void __cdecl SellThread1(void* param);
void __cdecl SellThread2(void* param);
int tickets = 100;
//个INVALID_HANDLE_VALUE ( vs2008下为0xfffffffff ) 实际值等于-1
//INVALID_HANDLE_VALUE类似与指针里的NULL,如果将指针释放后,应该立即将指针赋为NULL,否则出现野指针;
//同理,句柄执行closehandle后,应该立即将句柄置为INVALID_HANDLE_VALUE,即让句柄失效。
HANDLE hEvent = INVALID_HANDLE_VALUE;
int main()
{
//创建事件,此刻为有信号状态,自动重置信号状态,初始化为有信号状态,线程可以直接获取
hEvent = CreateEvent(NULL, FALSE, TRUE, L"事件对象");
Sleep(1000);
//主线程休眠1秒后,将信号量置为无信号状态
//ResetEvent(hEvent);
printf("开始卖票了!\n");
//创建两个售票线程
uintptr_t t1 = _beginthread(SellThread1, 0, "售票窗口A");
uintptr_t t2 = _beginthread(SellThread2, 0, "售票窗口B");
//无限等待两个线程全部执行完毕
HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };
WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
printf("卖票结束!\n");
system("pause");
return 0;
}
void __cdecl SellThread1(void* param){
char *name = reinterpret_cast<char*>(param);
while (tickets > 0){
//如果事件对象为信号状态(没有线程拥有它),则线程可以获取它后继续执行
//自动重置的事件对象,调用了WaitForSingleObject函数之后,自动重置为无信号,
//即其他线程不能再抢占了
WaitForSingleObject(hEvent, INFINITE);
if (tickets > 0){
Sleep(10);
}
//让事件变成有信号状态,相当于解锁
SetEvent(hEvent);
}
}
void __cdecl SellThread2(void* param){
char *name = reinterpret_cast<char*>(param);
while (tickets > 0){
WaitForSingleObject(hEvent, INFINITE);
if (tickets > 0){
Sleep(10);
printf("%s卖出第%d张票!\n", name, tickets--);
}
SetEvent(hEvent);
}
}
#endif
#if 0//利用事件对象实现一个程序只允许运行一个进程
#include<iostream>
#include<windows.h>
#include<stdio.h>
int main()
{
HANDLE hEvent = CreateEvent(NULL, FALSE, TRUE, L"事件对象");
if (GetLastError() == ERROR_ALREADY_EXISTS){
printf("程序已经运行了,退出!\n");
getchar();
CloseHandle(hEvent);
return 0;
}
printf("程序第一次运行!\n");
getchar();
return 0;
}
#endif
#if 0//利用semaphore实现程序只允许一个进程运行
#include<iostream>
#include<Windows.h>
#include<stdio.h>
int main()
{
HANDLE hSemaphore = CreateSemaphore(NULL, 3, 3, L"停车位");
if (GetLastError() == ERROR_ALREADY_EXISTS){
printf("程序已经运行,请不要开启多个进程!\n");
getchar();
CloseHandle(hSemaphore);
return 0;
}
printf("程序第一次运行!\n");
getchar();
CloseHandle(hSemaphore);
return 0;
}
#endif
#if 0 //采用互斥体来实现单进程运行
#include<iostream>
#include<Windows.h>
#include<stdio.h>
int main()
{
HANDLE hMutex = CreateMutex(NULL, FALSE, L"售票互斥体");
if (GetLastError() == ERROR_ALREADY_EXISTS){
printf("程序已经运行,退出\n");
getchar();
CloseHandle(hMutex);
return 0;
}
printf("第一次运行程序!\n");
getchar();
return 0;
}
#endif
#if 0 //信号量控制停车场车位
#include<windows.h>
#include<stdio.h>
DWORD WINAPI ThreadFun(LPVOID param);
struct Car{
char name[20];
DWORD time;
};
HANDLE hSemphore = INVALID_HANDLE_VALUE;
int main()
{
//初始化三个停车位资源
hSemphore = CreateSemaphore(NULL, 3, 3, L"停车场");
HANDLE hArr[5] = { INVALID_HANDLE_VALUE };
for (int i = 0; i < 5; ++i){
Car *pCar = new Car;
sprintf_s(pCar->name, "车辆%c", 'A' + i);
pCar->time = 3 + i * 3;
//创建车辆线程
hArr[i] = CreateThread(NULL, 0, ThreadFun, (LPVOID)pCar, 0, NULL);
}
//等待所有线程执行完毕
WaitForMultipleObjects(5, hArr, true, INFINITE);
return 0;
}
DWORD WINAPI ThreadFun(LPVOID param)
{
//如果有剩余车位资源(有信号状态),就放行(往下执行)
WaitForSingleObject(hSemphore, INFINITE);
Car *pCar = reinterpret_cast<Car*>(param);
printf("%s进入停车场,停车%d秒!\n", pCar->name, pCar->time);
Sleep(pCar->time * 1000);
printf("%s离开停车场!\n", pCar->name);
//释放一个停车位(信号量+1)
ReleaseSemaphore(hSemphore, 1, NULL);
return 0;
}
#endif
#if 0//互斥体 售票
#include<iostream>
#include<process.h>
#include<stdio.h>
#include<windows.h>
void __cdecl SellThread1(void* param);
void __cdecl SellThread2(void* param);
int tickets = 100;
HANDLE hMutex = INVALID_HANDLE_VALUE;
int main()
{
hMutex = CreateMutex(NULL, FALSE, L"售票互斥体");
printf("开始卖票了!\n");
uintptr_t t1 = _beginthread(SellThread1, 0, "售票窗口A");
uintptr_t t2 = _beginthread(SellThread2, 0, "售票窗口B");
HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };
WaitForMultipleObjects(2, hArr, true, INFINITE);
printf("卖票结束!\n");
system("pause");
return 0;
}
void __cdecl SellThread1(void* param){
char *name = reinterpret_cast<char *>(param);
while (tickets > 0){
//如果这个互斥体为有信号状态(没有线程拥有它),则线程获取它后继续执行
WaitForSingleObject(hMutex, INFINITE);
if (tickets > 0){
Sleep(10);
//CPU恰好执行到这里,这个时候线程的时间片到了,并且此时还剩最后一张票
printf("%s卖出第%d张票!\n", name, tickets--);
}
//释放对互斥体的拥有权 ,它变成有信号状态
ReleaseMutex(hMutex);
}
}
void __cdecl SellThread2(void* param){
char *name = reinterpret_cast<char *>(param);
while (tickets > 0){
WaitForSingleObject(hMutex, INFINITE);
if (tickets > 0){
Sleep(10);
printf("%s卖出第%d张票!\n", name, tickets--);
}
ReleaseMutex(hMutex);
}
}
#endif
#if 0 //pv操作 生产者 消费者模式 P操作指:通过 V操作指:释放
#include<windows.h>
#include<queue>
#include<process.h>
using namespace std;
queue<int> store;
int StoreSize = 3;//仓库可以放3个货物
int ID = 1;//货物起始ID
//随机时间数组,模拟随机生产和消费的速度
int arr1[10] = { 2, 1, 3, 5, 9, 2, 5, 2, 3, 7 };
//需要两个Event来通知
HANDLE hEvent1 = INVALID_HANDLE_VALUE;//有货物时通知消费者去取货物
HANDLE hEvent2= INVALID_HANDLE_VALUE;//仓库有空时通知生产者开始生产
//生产者
void ProducerThread(LPVOID param);
//消费者
void ConsumerThread(LPVOID param);
int main()
{
//需要先开始生产
hEvent1 = CreateEvent(NULL, TRUE, TRUE, L"事件对象1");
//一开始,仓库没货取
hEvent2 = CreateEvent(NULL, TRUE, FALSE, L"事件对象2");
uintptr_t t1 = _beginthread(ProducerThread, 0, NULL);
uintptr_t t2 = _beginthread(ConsumerThread, 0, NULL);
//无限等待两个线程运行结束
HANDLE hArr[] = { (HANDLE)t1, (HANDLE)t2 };
WaitForMultipleObjects(2, hArr, TRUE, INFINITE);
CloseHandle(hEvent1);
CloseHandle(hEvent2);
system("pause");
return 0;
}
//生产者
void ProducerThread(LPVOID param){
while (true)
{
WaitForSingleObject(hEvent1, INFINITE);//看event是否允许生产
if (store.size() < StoreSize)//仓库有空才生产
{
int id = ID++;
printf("生产货物:%d\n", id);
store.push(id);
Sleep(arr1[id % 10] * 1000);
}
else{//仓库满了
ResetEvent(hEvent1);//把事件设为无信号状态
printf("仓库满了!\n");
}
//如果仓库有货可以通知消费者来取货物了
if (store.size() > 0){
SetEvent(hEvent2);//让消费者的事件对象有信号
}
}
}
//消费者
void ConsumerThread(LPVOID param){
while (true)
{
//看event2是否允许取货物
WaitForSingleObject(hEvent2, INFINITE);
if (store.size() > 0){
int id = store.front(); store.pop();//获取队列中的货物
printf("\t\t\t取出货物:%d\n", id);
Sleep(arr1[(id + 3) % 10] * 1000);
}
else{//仓库空了
ResetEvent(hEvent2);//设为无信号,不能取货物了
printf("\t\t\t仓库空了!\n");
}
if (store.size() < 3){
SetEvent(hEvent1);//通知生产者继续生产
}
}
}
#endif
//-------------------- C++11 多线程 -------------------------
#if 0//原子操作 线程并发,非原子操作错误演示
#include<iostream>
#include<atomic>//原子操作头文件
#include<thread>
using namespace std;
enum {
T=100000
};
//atomic<int> N = 0;
int N = 0;
void ThreadFun(){
for (int i = 0; i < T/*2*T*/; ++i){
++N;//线程并发导致叠加操作,不是原子操作,因此肯定少于2T
}
}
int main(){
thread t1(ThreadFun);
thread t2(ThreadFun);
t1.join();
t2.join();
cout << N << endl;
system("pause");
}
#endif
#if 0//原子操作
#include<iostream>
#include<atomic>//原子操作头文件
#include<thread>
using namespace std;
enum {
T = 1000000
};
atomic<int> N = 0;//原子操作,避免多线程并发导致的叠加操作
//int N = 0;
void ThreadFun(){
for (int i = 0; i < T/*2*T*/; ++i){
++N;
}
}
int main(){
thread t1(ThreadFun);
thread t2(ThreadFun);
t1.join();
t2.join();
cout << N << endl;
system("pause");
}
#endif
#if 0//原子操作,十人赛跑
#include<iostream>
#include<atomic>
#include<thread>
#include<vector>
using namespace std;
using namespace std::this_thread;
atomic<bool> ready = false;//是否枪响
atomic_flag win = ATOMIC_FLAG_INIT;//终点线
void Run(int id){
//抢没响不能跑
while (!ready)
{
yield();//让其他线程先执行
}
for (int i = 0; i < 100000000; ++i){}
//如果没有设置过,返回false
if (!win.test_and_set()){
cout << id << " 号选手赢得第一名!" << endl;
}
}
int main(int id){
//十个选手赛跑
vector<thread> vecPlayer;
for (int i = 0; i < 10; ++i){
vecPlayer.push_back(thread(Run, i));
}
cout << "十个选手已经准备好了!" << endl;
//准备发命令
//sleep_for(chrono::seconds(3));
cout << "...3..." << endl;
sleep_for(chrono::seconds(1));
cout << "...2..." << endl;
sleep_for(chrono::seconds(1));
cout << "...1..." << endl;
//可以跑了
ready = true;
//等待所有选手跑完
for (thread &t : vecPlayer){
t.join();
}
system("pause");
return 0;
}
#endif
#if 0 //C++11 互斥锁-1
#include<iostream>
#include<mutex>
#include<thread>
#include<stdexcept>
using namespace std;
using namespace std::this_thread;
mutex m;
void ThreadFun()
{
try
{
for (int i = 0; i < 10; ++i)
{
sleep_for(chrono::seconds(1));
m.lock();
//lock_guard<mutex> lck(m);//哪怕发生异常也是可以安全解锁,因为lck会析构,然后解锁mutex
if (i == 3) throw logic_error("发生异常了!");//发生异常后m无法解锁,线程无法结束,所以程序会锁死无法向下执行
cout << "A打印" << i << endl;
m.unlock();//抛出异常时,导致没有unlock,使得B无法获取mutex, 死锁
}
}
catch (logic_error & e)
{
cout << "错误:" << e.what() << endl;
}
}
void ThreadFun2()
{
for (int i = 0; i < 10; ++i)
{
sleep_for(chrono::seconds(1));
//lock_guard<mutex> lck(m);
m.lock();
cout << "B打印" << i << endl;
m.unlock();
}
}
int main()
{
thread t1(ThreadFun);
thread t2(ThreadFun2);
t1.join();
t2.join();
return 0;
}
#endif
#if 0 //C++11 互斥锁-2
#include<iostream>
#include<mutex>
#include<thread>
#include<stdexcept>
using namespace std;
using namespace std::this_thread;
mutex m;
void ThreadFun()
{
try
{
for (int i = 0; i < 10; ++i)
{
sleep_for(chrono::seconds(1));
//m.lock();
lock_guard<mutex> lck(m);//哪怕发生异常也是可以安全解锁,因为lck会析构,然后解锁mutex
if (i == 3) throw logic_error("发生异常了!");
cout << "A打印" << i << endl;
//m.unlock();//抛出异常时,导致没有unlock,使得B无法获取mutex, 死锁
}
}
catch (logic_error & e)
{
cout << "错误" <<e.what()<< endl;
}
}
void ThreadFun2()
{
for (int i = 0; i < 10; ++i)
{
sleep_for(chrono::seconds(1));
lock_guard<mutex> lck(m);
//m.lock();
cout << "B打印" << i << endl;
//m.unlock();
}
}
int main()
{
thread t1(ThreadFun);
thread t2(ThreadFun2);
t1.join();
t2.join();
return 0;
}
#endif
#if 0//独占锁
#include<iostream>
#include<mutex>
#include<thread>
#include<stdexcept>
using namespace std;
using namespace std::this_thread;
mutex m;
void threadFun1(){
try{
for (int i = 0; i < 10; i++)
{
unique_lock<mutex> lck(m);
//m.lock();//
if (i == 3)
throw logic_error("发生异常了!");
cout << "A 打印: " << i << endl;
//m.unlock();//使用lck.lock()主动上锁,当抛出异常时,导致没有unlock,使得B无法获取mutex,死锁
//但是使用unique_lock则不会出现死锁的情况,离开作用于会自动解锁,但是也可以手动lck.unlock()来手动解锁
sleep_for(chrono::seconds(1));
}
}
catch (logic_error &e){
cout << "错误" << e.what() << endl;
}
}
void threadFun2(){
for (int i = 0; i < 10; i++)
{
unique_lock<mutex> lok(m);
cout << "打印B: " << i << endl;
//lok.unlock();//可以手动解锁,也可以不用
sleep_for(chrono::seconds(1));
}
}
int main()
{
thread t1(threadFun1);
thread t2(threadFun2);
t1.join();
t2.join();
system("pause");
return 0;
}
#endif
#if 0
#include<iostream>
#include<mutex>
#include<condition_variable>
#include<thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
condition_variable cv;//仅支持unique_lock<mutex>作为wait的参数
condition_variable_any cv2;//接受任何lockable参数作为wait的参数
mutex m;
void ThreadFun(int id){
unique_lock<mutex> lck(m);
cv.wait(lck);//等待被唤醒,否则一直卡在这里
cout << "线程ID: " << id << "执行!" << endl;
}
int main(){
thread t1(ThreadFun, 1);
thread t2(ThreadFun, 2);
thread t3(ThreadFun, 3);
cout << "3秒后被唤醒" << endl;
sleep_for(seconds(3));//3秒后被唤醒
//cv.notify_all();//唤醒所有线程
t1.join();
t2.join();
t3.join();
system("pause");
return 0;
}
#endif
#if 0 //async线程异步
#include<iostream>
#include<future>
#include<thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
int work(int a, int b)
{
cout << "开始计算:" << endl;
sleep_for(seconds(5));//假设某个计算需要耗时5s
return a + b;
}
int main(){
future<int> result = async(work, 123, 456);//线程同步函数
result.wait(); //等待线程结束运行
cout << "算出结果:" << endl;
int sum = result.get();//获取线程返回的结果
cout << "最终的结果是: " << sum << endl;
system("pause");
return 0;
}
#endif
#if 0
#include<iostream>
#include<future>
#include<thread>
using namespace std;
using namespace std::this_thread;
using namespace std::chrono;
void work(promise<int> &prom){
cout << "开始计算!" << endl;
sleep_for(seconds(3));
cout << "计算完成!" << endl;
prom.set_value(666);//promise 设置结果值 可以被future get到
}
int main()
{
//定义一个promise
promise<int> prom;
//future 和 promise 搭配使用,类似于aynsc
future<int> result = prom.get_future();
thread t1(work, ref(prom));
t1.detach();
int sum = result.get();
cout << "获取结果:" << sum << endl;
system("pause");
return 0;
}
#endif
C++ 练习-多线程
最新推荐文章于 2021-03-10 16:36:29 发布