编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。

1、Windows 

#include <stdio.h>
#include <process.h>
#include <windows.h>

// 线程个数
const int THREAD_NUM = 3;

// 循环次数
const int LOOP = 10;

// 子线程同步事件
HANDLE g_hThreadEvent[THREAD_NUM];
// 主线程与子线程同步
HANDLE g_Semaphore;
int g_Count = 0;

unsigned int __stdcall ThreadFunction(void *pPM)
{
    int num = *(int *)pPM;
    // 信号量++
    ReleaseSemaphore(g_Semaphore, 1, NULL);

    for (int i = 0; i < LOOP; i++)
    {
        // 等待该事件有效。
        WaitForSingleObject(g_hThreadEvent[num], INFINITE);
        g_Count++;

        printf("第%d次 线程ID:%3d,线程打印:%c\n ", g_Count, GetCurrentThreadId(), num + 'A');
        // 置位下一个事件有效。
        SetEvent(g_hThreadEvent[(num + 1) % THREAD_NUM]);
    }

    return 0;
}

int main(void)
{
    int i = 0;
    HANDLE hThreadHandle[THREAD_NUM];
    // 形参1:安全控制,一般为NULL
    // 形参2:资源的初始值。
    // 形参3:最大的资源数量。
    // 形参4:该信号量的名称。
    g_Semaphore = CreateSemaphore(NULL, 0, 1, NULL); // 当前0个资源,最大允许1个同时访问

    for (i = 0; i < THREAD_NUM; i++)
    {
        // 形参1:安全控制。
        // 形参2:该事件是手动复原(TRUE)还是自动复原(FALSE)。
        // 形参3:指定事件的初始状态。若为TRUE,则为有信号状态,若为FALSE,则为无信号状态。
        // 形参4:指定该事件的名称。
        g_hThreadEvent[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
    }

    for (i = 0; i < THREAD_NUM; i++)
    {
        // 创建线程
        hThreadHandle[i] = (HANDLE)_beginthreadex(nullptr, 0, ThreadFunction, &i, 0, nullptr);
        // 每次创建完线程,该信号量都会等待,直至线程执行到释放信号量的代码为止。
        WaitForSingleObject(g_Semaphore, INFINITE);
    }
    // 代码执行到这里,说明各个线程都已经执行到WaitForSingleObject,在等待确认信号。
    // 置位线程1的事件。
    SetEvent(g_hThreadEvent[0]);
    // 等待所有线程返回。
    WaitForMultipleObjects(THREAD_NUM, hThreadHandle, true, INFINITE);

    for (i = 0; i < THREAD_NUM; i++)
    {
        CloseHandle(hThreadHandle[i]);
        CloseHandle(g_hThreadEvent[i]);
    }

    CloseHandle(g_Semaphore);

    system("pause");
    return 0;
}

2、Linux 

#include <iostream>
#include <pthread.h>
#include <unistd.h>

// 标记指定的线程是否处于等待 cond 的状态。
// 1    处于等待 cond 的状态。
// 0    cond 已成立或者处于阻塞状态。
bool g_flag_CA, g_flag_AB, g_flag_BC;
pthread_mutex_t g_mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_condCA = PTHREAD_COND_INITIALIZER;
pthread_cond_t g_condAB = PTHREAD_COND_INITIALIZER;
pthread_cond_t g_condBC = PTHREAD_COND_INITIALIZER;

using PRINTFUNC = void *(*)(void *);

char g_cinfo[3] = {'A', 'B', 'C'};
char g_showcount = 10;

void MyCondWait(bool *pflag, pthread_cond_t *pcond, pthread_mutex_t *pmtx);
void MyCondSignal(bool *pflag, pthread_cond_t *pcond, pthread_mutex_t *pmtx);

void *PrintA(void *arg);
void *PrintB(void *arg);
void *PrintC(void *arg);

int main()
{
    PRINTFUNC printfunc[3] = {
        PrintA,
        PrintB,
        PrintC};

    const size_t threadcount = sizeof(printfunc) / sizeof(PRINTFUNC);
    pthread_t thread_pid[threadcount] = {0};
    for (size_t i = 0; i < threadcount; i++)
    {
        if (pthread_create(thread_pid + i, nullptr, printfunc[i], (void *)(g_cinfo + i)) != 0)
        {
            std::cout << "Failed to create thread." << std::endl;
            exit(1);
        }
    }
    // 加 sleep(1) 的作用是使三个线程在执行完 sleep(1) 之后,
    // 均堵塞在 pthread_cond_wait 。等待各自的条件的释放。
    sleep(1);

    pthread_mutex_lock(&g_mtx);
    MyCondSignal(&g_flag_CA, &g_condCA, &g_mtx);
    pthread_mutex_unlock(&g_mtx);

    for (size_t i = 0; i < threadcount; i++)
    {
        pthread_join(thread_pid[i], nullptr);
    }

    return 0;
}

void *PrintA(void *arg)
{
    char cinfo = *(char *)arg;
    char showcount = g_showcount;
    while (showcount--)
    {
        pthread_mutex_lock(&g_mtx);
        MyCondWait(&g_flag_CA, &g_condCA, &g_mtx);

        std::cout << 10 - showcount << "." << cinfo;

        MyCondSignal(&g_flag_AB, &g_condAB, &g_mtx);
        pthread_mutex_unlock(&g_mtx);   // 解的锁是 pthread_cond_wait 满足条件时加的锁。

        usleep(50);
    }
    // 防止线程 C ,在执行 MyCondSignal 函数时,由于 g_flag_CA = 0,导致程序执行在 while 循环中。
    g_flag_CA = true;
    return nullptr;
}

void *PrintB(void *arg)
{
    char cinfo = *(char *)arg;
    char showcount = g_showcount;
    while (showcount--)
    {
        pthread_mutex_lock(&g_mtx);
        MyCondWait(&g_flag_AB, &g_condAB, &g_mtx);

        std::cout << cinfo;

        MyCondSignal(&g_flag_BC, &g_condBC, &g_mtx);
        pthread_mutex_unlock(&g_mtx);

        usleep(50);
    }
    return nullptr;
}

void *PrintC(void *arg)
{
    char cinfo = *(char *)arg;
    char showcount = g_showcount;
    while (showcount--)
    {
        pthread_mutex_lock(&g_mtx);
        MyCondWait(&g_flag_BC, &g_condBC, &g_mtx);

        std::cout << cinfo << std::endl;

        MyCondSignal(&g_flag_CA, &g_condCA, &g_mtx);
        pthread_mutex_unlock(&g_mtx);

        usleep(50);
    }
    return nullptr;
}

// 标记并使指定的线程处于等待 cond 满足的状态。
void MyCondWait(bool *pflag, pthread_cond_t *pcond, pthread_mutex_t *pmtx)
{
    *pflag = true;
    pthread_cond_wait(pcond, pmtx);
    *pflag = false;
    return;
}

// 向指定的线程发出条件允许的通知。
void MyCondSignal(bool *pflag, pthread_cond_t *pcond, pthread_mutex_t *pmtx)
{
    while (!*pflag)
    {
        // 执行到这里,说明该线程阻塞在 while 循环开头的 pthread_mutex_lock 函数位置。
        // 需要调用 pthread_mutex_unlock() 函数将其解锁并执行到 pthread_cond_wait() 函数,使之处于等
        // 待 cond 的状态。
        pthread_mutex_unlock(&g_mtx);
        usleep(50);
        pthread_mutex_lock(&g_mtx);
    }
    // 执行到这里,说明指定的线程已经处于等待 cond 满足的状态。
    pthread_cond_signal(pcond);
    return;
}

 

(SAW:Game Over!)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值