多线程同步
线程之间同步是指线程等待其他线程执行完某个动作之后再执行(本文情况)。
线程同步还可以是像十字路口的红绿灯一样,只允许一个方向的车同行,其他方向的车等待。
本文将使用信号量来实现线程同步。
一个线程通知另一个线程,另一个线程等待被通知信号。
一个发送线程先往控制台上打印1,这时候接收线程并不往控制台打印2,而是等待发送线程发给自己的信号,等到信号之后再打印2.
每次发送线程打印完自己的数据之后,睡眠1毫秒,给接收线程时间来完成自己的工作。
睡眠1毫秒合理吗?
这里睡眠1毫秒是合理的。
多个线程在协调工作的时候,每个线程都会需要时间来才能解决问题。
所以作为协调源头的线程1,应该给其他线程时间来处理问题,这是合理的。
例如,在音视频开发中,采集是源头,比如120HZ的视频,时间间隔是8.333ms,所有后续的编码线程,推流线程,等等,都需要在这有限的8.333毫秒之内完成自己的工作。
STL 写法
cpp
// condition_variable::notify_one
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <chrono> //milliseconds
using namespace std;
using namespace chrono;
std::mutex mutex1;
std::condition_variable event;
void thread_sender_fun(void)
{
while (true)
{
cout << "1";
event.notify_one();
this_thread::sleep_for(milliseconds(1));
}
}
void thread_receiver_fun()
{
while (true)
{
std::unique_lock<std::mutex> lock(mutex1);
event.wait(lock);
cout << "2";
}
}
int main()
{
std::thread thread_sender(thread_sender_fun);
std::thread thread_receiver(thread_receiver_fun);
// join them back:
thread_sender.join();
thread_receiver.join();
return 0;
}
Windows 写法
cpp
#include <windows.h>
#include <iostream>
using namespace std;
HANDLE event;//事件对象
DWORD WINAPI sender_event_thread_fun(LPVOID lpParam)
{
while (true)
{
cout << "1";//干活
SetEvent(event);//发出写完成信号,通知另一个线程该打印2了
Sleep(1);
}
return 0;
}
DWORD WINAPI receive_event_thread_fun(LPVOID lpParam)
{
UNREFERENCED_PARAMETER(lpParam);
while (true)
{
DWORD dwWaitResult = WaitForSingleObject(event, INFINITE);// 等待信号,无限等待
cout << "2";//干活
}
return 0;
}
int main(void)
{
event = CreateEvent(NULL,
//是否需要人工ResetEvent重置为无信号状态:
//是:当该事件为有信号状态时,所有等待该信号的线程都变为可调度线程。
// 并且,需要手动调用ResetEvent为无信号状态;
//否:当该事件为有信号状态时,只有一个线程变为可调度线程。
// 并且,系统自动调用ResetEvent将该对象设置为无信号状态。(一次性的信号)
FALSE,
FALSE,//初始状态:无信号状态
TEXT("WriteFinishedEvent")// 事件对象名称
);
//创建线程
HANDLE thread_sender = CreateThread(NULL, 0, sender_event_thread_fun, NULL, 0, NULL);
HANDLE thread_receive = CreateThread(NULL, 0, receive_event_thread_fun, NULL, 0, NULL);
HANDLE handleArr[] = { thread_sender , thread_receive };
//等待线程执行结束
WaitForMultipleObjects(2, handleArr, TRUE, INFINITE);
//释放资源
CloseHandle(thread_sender);
CloseHandle(thread_receive);
CloseHandle(event);
return 0;
}
不再乱箭穿心,总是先打印1,后打印2
Linux 写法
cpp
#include <pthread.h>
#include <semaphore.h>
#include <iostream>
#include <unistd.h>//usleep
using namespace std;
sem_t event;
void* thread_sender_fun(void* arg)
{
while (true)
{
cout << "1";
sem_post(&event);
usleep(1000);//休眠一毫秒
}
return 0;
}
void* thread_receive_fun(void* arg)
{
while (true)
{
sem_wait(&event);
cout << "2";
}
return 0;
}
int main(int argc, char *argv[])
{
pthread_t thread_sender;
pthread_t thread_receiver;
sem_init(&event, 0, 0);
pthread_create(&thread_sender, NULL, thread_sender_fun, NULL);
pthread_create(&thread_receiver, NULL, thread_receive_fun, NULL);
pthread_join(thread_sender, NULL);
pthread_join(thread_receiver, NULL);
return 0;
}
不再乱箭穿心,总是先打印1,后打印2