ABCABC…

8 篇文章 0 订阅

迅雷笔试题:

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

Windows(VC9下编译运行通过):

#include <iostream>
#include <windows.h>
#include <process.h>
using namespace std;

#define PRINT_TIMES 10
// 考虑到可读性 多写几个handle
// #define THREAD_NUMS 3

// 用于打印字符控制,有点类似循环链表
struct sPrintControl
{
	char cPrint;
	HANDLE hEventThis;
	HANDLE hEventNext;
};

// 按照顺序打印字符
UINT WINAPI vPrintCharWithSeq(LPVOID p_psPrintControl)
{
	sPrintControl* l_psPrintControl = static_cast<sPrintControl*>(p_psPrintControl);

	char l_cChar = l_psPrintControl->cPrint;

	for (int i = 0; i < PRINT_TIMES; i++)
	{
		// wait for print
		WaitForSingleObject(l_psPrintControl->hEventThis, INFINITE);
		cout<<"ThreadId:"<<GetCurrentThreadId()<<' '<<i<<l_cChar<<endl;
		// signal the next thread
		SetEvent(l_psPrintControl->hEventNext);
	}

	return 0;
}

int main()
{
	HANDLE l_hThreadA = NULL;
	HANDLE l_hThreadB = NULL;
	HANDLE l_hThreadC = NULL;
	HANDLE l_hThreadAEvent = NULL;
	HANDLE l_hThreadBEvent = NULL;
	HANDLE l_hThreadCEvent = NULL;

	// 自动重置,从ThreadA开始打印
	l_hThreadAEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
	l_hThreadBEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	l_hThreadCEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

	sPrintControl l_sPrintControl[3] = { 
		{'A', l_hThreadAEvent, l_hThreadBEvent}, 
		{'B', l_hThreadBEvent, l_hThreadCEvent}, 
		{'C', l_hThreadCEvent, l_hThreadAEvent}
	};

	l_hThreadA = (HANDLE)_beginthreadex(NULL, 0, vPrintCharWithSeq, &l_sPrintControl[0], THREAD_PRIORITY_NORMAL, NULL);
	l_hThreadB = (HANDLE)_beginthreadex(NULL, 0, vPrintCharWithSeq, &l_sPrintControl[1], THREAD_PRIORITY_NORMAL, NULL);
	l_hThreadC = (HANDLE)_beginthreadex(NULL, 0, vPrintCharWithSeq, &l_sPrintControl[2], THREAD_PRIORITY_NORMAL, NULL);

	// 等待线程结束
	WaitForSingleObject(l_hThreadA, INFINITE);
	WaitForSingleObject(l_hThreadB, INFINITE);
	WaitForSingleObject(l_hThreadC, INFINITE);

	// 释放
	CloseHandle(l_hThreadA);
	CloseHandle(l_hThreadB);
	CloseHandle(l_hThreadC);
	CloseHandle(l_hThreadAEvent);
	CloseHandle(l_hThreadBEvent);
	CloseHandle(l_hThreadCEvent);

	return 0;
}

Linux:

    感谢Jinhao的帮助。用pthread_cond_t解决了。实际上测试用sem_t还快一点。因为用sem_t的方法类似windows下面用Event就不贴代码了。

线程关键代码:

void * thread(thr_id* t)
{
    pthread_mutex_lock(t->mutex); //这个lock相当重要
    sem_post(t->sem);
    pthread_cond_wait(t->self_cond, t->mutex);
    pthread_mutex_unlock(t->mutex);

    //真正开始
    for(int i = 0; i < 10; ++i)
    {
        pthread_mutex_lock(t->mutex);
        std::cout<<t->id<<std::flush;
        pthread_cond_signal(t->next_cond);
        if(i < 9) //输出最后一遍的时候,不用再wait而是退出线程
            pthread_cond_wait(t->self_cond, t->mutex);
        pthread_mutex_unlock(t->mutex);
    }
}

Jinhao:现在C唤醒A的时候,能保证A是wait的状态.因为A在cond_wait的时候,B才能获得锁,当b在cond_wait的时候,C才获得锁.所以当C cond_signal A时, A必然是cond_wait的。

全部代码如下:

#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <semaphore.h>
using namespace std;

struct thr_id
{
    char id;
    sem_t * sem;
    pthread_mutex_t * mutex;
    pthread_cond_t * self_cond;
    pthread_cond_t * next_cond;
};

void * thread(thr_id* t)
{
    pthread_mutex_lock(t->mutex);
    sem_post(t->sem);
    pthread_cond_wait(t->self_cond, t->mutex);
    pthread_mutex_unlock(t->mutex);

    for(int i = 0; i < 10000; ++i)
    {
        pthread_mutex_lock(t->mutex);
        std::cout<<t->id<<std::flush;
        pthread_cond_signal(t->next_cond);
        if(i < 9999)
            pthread_cond_wait(t->self_cond, t->mutex);
        pthread_mutex_unlock(t->mutex);
    }
}

typedef void* (*PRINTTHREADFUNC) (void*);

int main()
{
    pthread_t th_a, th_b, th_c;

    sem_t sem;
    sem_init(&sem, 0, 0);

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    pthread_cond_t cond_a = PTHREAD_COND_INITIALIZER;
    pthread_cond_t cond_b = PTHREAD_COND_INITIALIZER;
    pthread_cond_t cond_c = PTHREAD_COND_INITIALIZER;

    thr_id thrids[3] = {
        {'a', &sem, &mutex, &cond_a, &cond_b},
        {'b', &sem, &mutex, &cond_b, &cond_c},
        {'c', &sem, &mutex, &cond_c, &cond_a}
    };

    pthread_create(&th_a, NULL, reinterpret_cast<PRINTTHREADFUNC>(thread), &thrids[0]);
    pthread_create(&th_b, NULL, reinterpret_cast<PRINTTHREADFUNC>(thread), &thrids[1]);
    pthread_create(&th_c, NULL, reinterpret_cast<PRINTTHREADFUNC>(thread), &thrids[2]);

    for(int i = 0; i < 3; ++i)
    {
        sem_wait(&sem);
    }

    pthread_mutex_lock(&mutex);
    pthread_cond_signal(thrids[0].self_cond);
    pthread_mutex_unlock(&mutex);

    pthread_join(th_a, NULL);
    pthread_join(th_b, NULL);
    pthread_join(th_c, NULL);

    sem_destroy(&sem);
    pthread_cond_destroy(&cond_a);
    pthread_cond_destroy(&cond_b);
    pthread_cond_destroy(&cond_c);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值