两个线程同步执行:解决乱箭穿心(STL/Windows/Linux)

C++自学精简教程 目录(必读)

C++并发编程入门 目录

多线程同步

线程之间同步是指线程等待其他线程执行完某个动作之后再执行(本文情况)。

线程同步还可以是像十字路口的红绿灯一样,只允许一个方向的车同行,其他方向的车等待。

本文将使用信号量来实现线程同步。

一个线程通知另一个线程,另一个线程等待被通知信号。

一个发送线程先往控制台上打印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

相关推荐
hjjdebug3 分钟前
linux 下 signal() 函数的用法,信号类型在哪里定义的?
linux·signal
其乐无涯4 分钟前
服务器技术(一)--Linux基础入门
linux·运维·服务器
Diamond技术流4 分钟前
从0开始学习Linux——网络配置
linux·运维·网络·学习·安全·centos
写bug的小屁孩7 分钟前
前后端交互接口(三)
运维·服务器·数据库·windows·用户界面·qt6.3
斑布斑布7 分钟前
【linux学习2】linux基本命令行操作总结
linux·运维·服务器·学习
紅色彼岸花14 分钟前
第六章:DNS域名解析服务器
运维·服务器
Spring_java_gg18 分钟前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
此生只爱蛋18 分钟前
【手撕排序2】快速排序
c语言·c++·算法·排序算法
✿ ༺ ོIT技术༻18 分钟前
Linux:认识文件系统
linux·运维·服务器
blammmp26 分钟前
Java:数据结构-枚举
java·开发语言·数据结构