C++中线程的切换

wangjie1986 2010-01-25 03:33:16
#include<iostream.h>
#include<windows.h>

DWORD WINAPI ThreadProc1(
LPVOID lpParameter // thread data
);
DWORD WINAPI ThreadProc2(
LPVOID lpParameter // thread data
);

int tickets=20;
void main()
{
HANDLE hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
HANDLE hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

CloseHandle(hThread1);
CloseHandle(hThread2);

cout<<"the main thread is running:"<<endl;
Sleep(4000);
cout<<"the main thread is over!"<<endl;


}
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
while(1)
{
if(tickets>0)
{

cout<<"ThreadProc1 sells ticket's num:"<<tickets--<<endl;
}
}
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
while(1)
{
if(tickets>0)
{
cout<<"ThreadProc2 sells ticket's num:"<<tickets--<<endl;
}
}
}
#include<iostream.h>
#include<windows.h>

DWORD WINAPI ThreadProc1(
LPVOID lpParameter // thread data
);
DWORD WINAPI ThreadProc2(
LPVOID lpParameter // thread data
);

int tickets=20;
void main()
{
HANDLE hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);
HANDLE hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

CloseHandle(hThread1);
CloseHandle(hThread2);

cout<<"the main thread is running:"<<endl;
Sleep(4000);
cout<<"the main thread is over!"<<endl;


}
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
while(1)
{
if(tickets>0)
{

cout<<"ThreadProc1 sells ticket's num:"<<tickets--<<endl;
}
}
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
while(1)
{
if(tickets>0)
{
cout<<"ThreadProc2 sells ticket's num:"<<tickets--<<endl;
}
}
}
the main thread is running:
ThreadProc1 sells ticket's num:20
ThreadProc1 sells ticket's num:19
ThreadProc1 sells ticket's num:18
ThreadProc1 sells ticket's num:17
ThreadProc1 sells ticket's num:16
ThreadProc1 sells ticket's num:15
ThreadProc1 sells ticket's num:14
ThreadProc1 sells ticket's num:13
ThreadProc1 sells ticket's num:12
ThreadProc1 sells ticket's num:11
ThreadProc1 sells ticket's num:10
ThreadProc1 sells ticket's num:9
ThreadProc1 sells ticket's num:8
ThreadProc1 sells ticket's num:7
ThreadProc1 sells ticket's num:6
ThreadProc1 sells ticket's num:5
ThreadProc1 sells ticket's num:5

ThreadProc2 sells ticket's num:4
ThreadProc2 sells ticket's num:3
ThreadProc2 sells ticket's num:2
ThreadProc2 sells ticket's num:1
the main thread is over!
Press any key to continue

刚学线程编程,实在不懂,为什么线程1第一次切换时会输出两次5?而且还均由线程1输出!(红色代码处)还请各位指教!
...全文
569 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
tony_chenypc 2010-01-25
  • 打赏
  • 举报
回复
#include <iostream>
#include <windows.h>

using namespace std;

HANDLE g_hMutex;

DWORD WINAPI ThreadProc1(
LPVOID lpParameter
);
DWORD WINAPI ThreadProc2(
LPVOID lpParameter
);

int tickets=20;
int main(int argc,char* argv[])
{
g_hMutex = ::CreateMutexA(NULL,FALSE,"g_hMutex");

cout << "the main thread is running:" << endl;

DWORD dwThreadID[2];
HANDLE hThread[2];
hThread[0] = CreateThread(NULL,0,ThreadProc1,NULL,0,&dwThreadID[0]);
hThread[1] = CreateThread(NULL,0,ThreadProc2,NULL,0,&dwThreadID[1]);

::WaitForMultipleObjects(2,hThread,TRUE,1000 * 24);

CloseHandle(hThread[0]);
CloseHandle(hThread[1]);
CloseHandle(g_hMutex);

cout << "the main thread is over!" << endl;

system("pause");

return 0;
}
DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
while(1)
{
if(tickets > 0)
{
::WaitForSingleObject(g_hMutex,INFINITE);
cout << "ThreadProc1 sells ticket's num:" << tickets-- << endl;
Sleep(1000);
::ReleaseMutex(g_hMutex);
}
}
}
DWORD WINAPI ThreadProc2(LPVOID lpParameter)
{
while(1)
{
if(tickets > 0)
{
::WaitForSingleObject(g_hMutex,INFINITE);
cout << "ThreadProc2 sells ticket's num:" << tickets-- << endl;
Sleep(1000);
::ReleaseMutex(g_hMutex);
}
}
}
hityct1 2010-01-25
  • 打赏
  • 举报
回复
没有互斥
lin_style 2010-01-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 wangjie1986 的回复:]
我知道,线程访问共享变量应该加锁,此处只是为想知道这种情况产生的原因。 我想线程1输出5后,此时切换到线程2,即使线程1输出tickets=5时,发生切换,即没来得执行tickets--就切换了,也就是说线程2会输出5,然后ticket--变为4,然后线程2继续运行,按道理即使会输出两个5,也是线程1和线程2各输出一个5啊,就是不明白为什么线程1会输出一个值两遍!

[/Quote]
很正常啊,这样模拟
假设现在tickerts是6
线程1拿到,保存在寄存器
线程2也拿到,保存在寄存器


线程1减去,并且回写内存,打出5
线程2减去,并且回写内存(还是5),这时候时间片被线程1抢占,线程1继续输出,

接着线程1又减成3,线程2开始输出。。


因为有个内存-寄存器的过程,再加上时间片的优先级,什么情况都能发生,只要你能想得到。
所以就这样。。。

cattycat 2010-01-25
  • 打赏
  • 举报
回复
cout不是线程安全的,用printf(),代码好长啊。
wangjie1986 2010-01-25
  • 打赏
  • 举报
回复
我知道,线程访问共享变量应该加锁,此处只是为想知道这种情况产生的原因。 我想线程1输出5后,此时切换到线程2,即使线程1输出tickets=5时,发生切换,即没来得执行tickets--就切换了,也就是说线程2会输出5,然后ticket--变为4,然后线程2继续运行,按道理即使会输出两个5,也是线程1和线程2各输出一个5啊,就是不明白为什么线程1会输出一个值两遍!
lin_style 2010-01-25
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 kennywang010 的回复:]
没有加锁的多线程在不同的电脑上有不同的结果,在这里讨论什么寄存器有意义吗?
[/Quote]

怎么没意义。
kennywang010 2010-01-25
  • 打赏
  • 举报
回复
没有加锁的多线程在不同的电脑上有不同的结果,在这里讨论什么寄存器有意义吗?
yuzl32 2010-01-25
  • 打赏
  • 举报
回复
cout < < ... < < tickets-- < <endl; 这句,它相当于执行如下代码:
MOV EAX, [ticket] ;1:将0移入寄存器
call cout .. ;2:调用输出
DEC EAX ;3:使eax自减1
MOV [ticket], EAX ;4:保存到ticket上。

我们可以发现,当线程一运行到2位置时,线程一暂停,线程二运行,那么就会出现输出值一样的效果。
kennywang010 2010-01-25
  • 打赏
  • 举报
回复
因为你的电脑性能差,切换线程卡了一下
Qlaiaqu 2010-01-25
  • 打赏
  • 举报
回复
两个线程同时造修改tickets,这就导致了你在任何时刻都不知道tickets的值,所以输出tickets的值有问题也正常。
常规的设置中,对于共享变量的访问是需要加锁的!!!
lovesi3344 2010-01-25
  • 打赏
  • 举报
回复

好长的代码
wangjie1986 2010-01-25
  • 打赏
  • 举报
回复
不好意思,上面的代码帖子两遍,线程一既然输出了5,然后执行tickets--,tickets=4,为什么线程1会两次输出5啊,我还没太弄懂ls说的意思,能在讲清楚一点吗,谢谢了
lin_style 2010-01-25
  • 打赏
  • 举报
回复
因为对一个变量赋值的时候是做了两部分操作,
一,先把内存中的数放到寄存器中进行操作
二,从寄存器中读回

WINDOWS是个抢占的操作系统,线程1可能到第一部分的时候就轮到线程2执行了。而这时候中内存数是不变的,于是线程2就又吧值赋值到寄存器中。。线程2返回的就是旧的了。

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧