多线程编程中Sleep函数导致语句重复执行解决思路

多线程编程中Sleep函数导致语句重复执行
#include <WINDOWS.H>
#include <STDIO.H>


DWORD WINAPI BuyTicket(LPVOID lpParameter);
DWORD WINAPI BuyTicket2(LPVOID lpParameter);

void main()
{

//
//创建n个买票线程
//

if (CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)BuyTicket,NULL,0,NULL) == NULL)
{
printf("CreateThread BuyTicket1 Failed!\n");
return;
}

if (CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)BuyTicket2,NULL,0,NULL) == NULL)
{
printf("CreateThread BuyTicket2 Failed!\n");
return;
}

int a;
scanf("%d",&a);
}



//剩余票数
int g_Tickets = 1;
/********************************************************************
Function Name: 第一个线程
*********************************************************************/
DWORD WINAPI BuyTicket(LPVOID lpParameter)
{
printf("I am in Thread 1 now!\n");


//检查是否还有票
if (g_Tickets > 0)
{
Sleep(2);
printf("\t线程1 说 : 我买到票了!\n");
g_Tickets--;
}
else
{
printf("\t线程1 说 : 没有票了!\n");
}


printf("1 : ticket is = %d \n",g_Tickets);
printf("I am exiting Thread 1 ....\n");

return 0;
}


/********************************************************************
Function Name: 第二个线程
*********************************************************************/
DWORD WINAPI BuyTicket2(LPVOID lpParameter)
{
printf("I am in Thread 2 now!\n");


//检查是否还有票
if (g_Tickets > 0)
{
printf("\t线程2 说 : 我买到票了!\n");
//Sleep(2);
g_Tickets--;
}
else
{
printf("\t线程2 说 : 没有票了!\n");
}


Sleep(2);
printf("2 : ticket is = %d \n",g_Tickets);
printf("I am exiting Thread 2 ....\n");

return 0;
}

运行结果:

I am in Thread 1 now!
I am in Thread 2 now!
  线程2 说 : 我买到票了!
  线程1 说 : 我买到票了!
  线程1 说 : 我买到票了!
2 : ticket is = 0
1 : ticket is = -1
I am exiting Thread 2 ....
I am exiting Thread 1 ....


总是有一行代码会重复执行,好像总是出现在第一个创建的线程当中,这是为什么呢?

------解决方案--------------------
你的g_Tickets操作的时候没有进行保护,在你
if (g_Tickets > 0) 

printf("\t线程2 说 : 我买到票了!\n"); 
g_Tickets--; 

的代码里,判断完g_Tickets是否大于0之后,另外一个线程完全有机会在你g_Tickets--之前改变这个值,加个互斥进行保护吧,
比如CMutex
------解决方案--------------------
你试着换一下CRuntime库的版本试试,换一个多线程版的。
------解决方案--------------------
SLEEP结束时要重新执行一遍原来的代码
================================

这是不可能的。


只所以输出了两次是因为线程退出前执行了两次,这里有一个问题需要注意的是如何防止冲突,比如“1 : ticket is = -1 ”是一种不允许出现的情况
------解决方案--------------------
建议: 
1、对 g_Tickets 申明前加上“volatile”关键字; 
2、在多线程中避免用 Sleep() 函数。
------解决方案--------------------
我估计是标准输出没有被保护所致。大概得流程如下:

线程1得到控制权,输出:I am in Thread 1 now! 
线程2得到控制器:输出:I am in Thread 2 now! 
线程2输出:线程2 说 : 我买到票了!
线程1得到控制权,输出:线程1 说 : 我买到票了!
线程1记录当前流指针,然后sleep
线程2得到控制权,输出2 : ticket is = %d \n",g_Tickets
输出后,他刷新输出缓存,由于此时流得指针还指向线程1当时得流指针(流是进程共享得),因此输出线程1 说 : 我买到票了!
此时线程1再输出一遍(因为他记录了流指针)

大致步骤如此,细节可能不同,因此无论你使用何种公共资源,都必须进行多线程保护,否则结果是“不可预期”得。也许是这种结果,也许是哪种结果