我的程序 是一个主线程
并且另外开了 两个线程。
主线程内  对全局变量 i 进行 ++  
然后让 其他两个线程 判断。
当i满足 各自 要求  就打印 i现在 我就怕  主线程 突然 运行两次 ,
直接有一个数字没判断那就达不到预期的效果。。怎么做  能避免呢?// 3535.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include "resource.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include "afxmt.h"
#include <Windows.h>#ifdef _DEBUG
#define new DEBUG_NEW
#endifusing namespace std;volatile int sun=1;
volatile int i=0;
CCriticalSection chao ;void thread1_function();
void thread2_function();
 //唯一的应用程序对象//CWinApp theApp;
//CWinApp theApp 本来是有的,但是注释掉了也没事。             不知道为啥?????int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0; // 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
}
HANDLE t1;
HANDLE t2; //int i;
//i=0; int j;
cout<<"范围请输入";
cin>>j;
cout<<"ok,将在0----"<<j<<"内查找能整除3和5的数字"<<endl; t1 = CreateThread(NULL, 
//t1 = CreateThread 函数返回值   
0,
(LPTHREAD_START_ROUTINE )thread1_function, 
//新起 线程 起始函数 thread1_function
NULL,
0,
NULL);
if (t1 == NULL) 
{
//如果 t1 为 空  新起线程 失败 
perror("Calling pthread1_create failed.");
exit(-1);
}
t2 = CreateThread(NULL, 
//t1 = CreateThread 函数返回值   
0,
(LPTHREAD_START_ROUTINE )thread2_function, 
//新起 线程 起始函数 thread2_function
NULL,
0,
NULL);
if (t2 == NULL) {
//如果 t2 为 空  新起线程 失败 
perror("Calling pthread2_create failed.");
exit(-2);
}
while(i<j)
{
chao.Lock(); 
i = i+1 ;
cout<<i<<endl;
chao.Unlock();
}
sun = 0;
//WaitForSingleObject函数用来检测hHandle事件的信号状态,
//当函数的执行时间超过dwMilliseconds就返回,
//但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
//否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。
WaitForSingleObject(t1, INFINITE);//等结束。
CloseHandle(t1);//关闭t1 线程 WaitForSingleObject(t2, INFINITE);//等结束。
CloseHandle(t2);//关闭t1 线程
system("pause") ;
return nRetCode;
}void thread1_function( )//yi xian
{
//cout<<"thread1....."<<endl; while(sun != 0) 
{
chao.Lock();//锁住 i 。进行判断。
if (i%3 ==0)
{
cout<<"线程2中,i的值"<<i<<"除以3,为整数"<<endl;
}
chao.Unlock();//开锁
}       }void thread2_function( )
{ while(sun != 0) 
{
chao.Lock(); //锁住 i 。进行判断。
if (i%5 ==0)
{
cout<<"线程3中,i的值"<<i<<"除以5,为整数"<<endl;
}
chao.Unlock();//开锁
}       }
摆脱谁给讲讲。而且,我写这东西吧,要是范围大 ,cpu占用就会很高。。原本5%   运行了,可能达到20%。。我机器 是 4核的,2G 的

解决方案 »

  1.   

    有一个问题啊。
       while(i<j)
        {
            chao.Lock(); 
            i = i+1 ;
            cout<<i<<endl;
            chao.Unlock();
        }    
        sun = 0;
    当你把sun = 0;的时候这个地方没有用临界区,容易出问题啊。
      

  2.   


    不明白。啥样子?Mutex  ?
      

  3.   

    刚开始我看出了,呵呵。
    使用互斥量,可以预防你的程序双重启动。
    当程序开始运行的时候,主线程被创建。主线程为什么会运行两次呢。你用sun这个变量来做循环的控制,换作手动的Event可能会更好。
      

  4.   

    Mutex 是可以跨进程使用的。
    首先CreateMutex创建一个Mutex。
    HANDLE CreateMutex( 
      LPSECURITY_ATTRIBUTES lpMutexAttributes, //这个参数设置为NULL
      BOOL bInitialOwner,                      //设置为TRUE,创建这个Mutex的对象占有这个Mutex对象
      LPCTSTR lpName                           //给这个Mutex对象起一个名字
    );创建成功会返回有一个有效的句柄。如果这个Mutex对象已经被创建,下次再创建的时候 就会失败。 把创建Mutex的代码放在程序的入口处,如果创建失败就返回。这样就可以控制程序的二重启动。其他进程,线程可以通过OpenMutex这个API来占用一个Mutex对象,如果Mutex对象被其他线程或进程占用那么OpenMutex将运行失败。当不在需要一个Mutex对象时,需要使用ReleaseMutex来释放掉这个Mutex对象。当一个Mutex对象被释放后,再用OpenMutex就会成功。具体该如何使用,就开实际的应用了。
      

  5.   


    那和锁 有什么区别?lock 以后 其他线程 若想 进行 操作 会被阻塞。直到解锁(unlock)  
    这种做法 也能保证 同一时刻只有一个线程 正在处理 共享数据。
    我要的是协调。。哎,苦命的孩啊。。真是不好找啊。我所说的协调  就是 ,主线程 必须等到 另外两个线程执行一遍  他才能执行 i++。上面 那个例子 运行 基本不会出什么 问题。我又写了一个。开了8个线程问题就明显了。代码如下。在开始阶段  主线程没等 另外的线程 判断玩,就运行了 ++   所以结果是错误的。
      

  6.   


    #include <stdio.h>
    #include <tchar.h>
    #include <iostream>
    #include "afxmt.h"
    #include <Windows.h>
    using namespace std;volatile int sun=1;
    volatile int i=0;
    CCriticalSection chao ;void thread1_function();
    void thread2_function();
    void thread3_function();
    void thread4_function();
    void thread5_function();
    void thread6_function();
    //唯一的应用程序对象//CWinApp theApp;
    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    int nRetCode = 0; // 初始化 MFC 并在失败时显示错误
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
    // TODO: 更改错误代码以符合您的需要
    _tprintf(_T("错误: MFC 初始化失败\n"));
    nRetCode = 1;
    }
    else
    {
    // TODO: 在此处为应用程序的行为编写代码。
    }
    HANDLE t1;
    HANDLE t2;
    HANDLE t3;
    HANDLE t4;
    HANDLE t5;
    HANDLE t6;
    //int i;
    //i=0; int j;
    cout<<"范围请输入";
    cin>>j;
    cout<<"ok,将在0----"<<j<<"内查找能整除3和5的数字"<<endl; t1 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread1_function, 
    //新起 线程 起始函数 thread1_function
    NULL,
    0,
    NULL);
    if (t1 == NULL) 
    {
    //如果 t1 为 空  新起线程 失败 
    perror("Calling pthread1_create failed.");
    exit(-1);
    }
    t2 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread2_function, 
    //新起 线程 起始函数 thread2_function
    NULL,
    0,
    NULL);
    if (t2 == NULL) {
    //如果 t2 为 空  新起线程 失败 
    perror("Calling pthread2_create failed.");
    exit(-2);
    }
    t3 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread3_function, 
    //新起 线程 起始函数 thread3_function
    NULL,
    0,
    NULL);
    if (t3 == NULL) 
    {
    //如果 t1 为 空  新起线程 失败 
    perror("Calling pthread1_create failed.");
    exit(-3);
    }
    t4 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread4_function, 
    //新起 线程 起始函数 thread4_function
    NULL,
    0,
    NULL);
    if (t4 == NULL) 
    {
    //如果 t1 为 空  新起线程 失败 
    perror("Calling pthread1_create failed.");
    exit(-4);
    }
    t5 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread5_function, 
    //新起 线程 起始函数 thread1_function
    NULL,
    0,
    NULL);
    if (t5 == NULL) 
    {
    //如果 t1 为 空  新起线程 失败 
    perror("Calling pthread1_create failed.");
    exit(-5);
    }
    t6 = CreateThread(NULL, 
    //t1 = CreateThread 函数返回值   
    0,
    (LPTHREAD_START_ROUTINE )thread6_function, 
    //新起 线程 起始函数 thread1_function
    NULL,
    0,
    NULL);
    if (t6 == NULL) 
    {
    //如果 t1 为 空  新起线程 失败 
    perror("Calling pthread1_create failed.");
    exit(-6);
    }
    while(i<j)
    {
    chao.Lock(); 
    i = i+1 ;
    //Sleep(200);
    cout<<i<<endl;
    chao.Unlock();
    ///*if (i>j)
    //{
    //
    // break;
    //}*/
    }
    sun = 0;
    //WaitForSingleObject函数用来检测hHandle事件的信号状态,
    //当函数的执行时间超过dwMilliseconds就返回,
    //但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
    //否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。
    WaitForSingleObject(t1, INFINITE);//等结束。
    CloseHandle(t1);//关闭t1 线程 WaitForSingleObject(t2, INFINITE);//等结束。
    CloseHandle(t2);//关闭t1 线程
    WaitForSingleObject(t3, INFINITE);//等结束。
    CloseHandle(t3);//关闭t1 线程
    WaitForSingleObject(t4, INFINITE);//等结束。
    CloseHandle(t4);//关闭t1 线程
    WaitForSingleObject(t5, INFINITE);//等结束。
    CloseHandle(t5);//关闭t1 线程
    WaitForSingleObject(t6, INFINITE);//等结束。
    CloseHandle(t6);//关闭t1 线程
    system("pause") ;
    return nRetCode;
    }
    //
    //int main()
    //{
    //
    //
    // return 0;
    //
    //}
    void thread1_function( )//yi xian
    {
    //cout<<"thread1....."<<endl; while(sun != 0) 
    {
    chao.Lock();//锁住 i 。进行判断。
    if (i%3 ==0)
    {
    cout<<"线程1中,i的值"<<i<<"除以3,为整数@@@@@@@@@@@@"<<endl;
    }
    chao.Unlock();//开锁
    }       }void thread2_function( )
    { while(sun != 0) 
    {
    chao.Lock(); //锁住 i 。进行判断。
    if (i%5 ==0)
    {
    cout<<"线程2中,i的值"<<i<<"除以5,为整数##############"<<endl;
    }
    chao.Unlock();//开锁
    }       }
    void thread3_function( )
    { while(sun != 0) 
    {
    chao.Lock(); //锁住 i 。进行判断。
    if (i%6 ==0)
    {
    cout<<"线程3中,i的值"<<i<<"除以6,为整数$$$$$$$$$$$$"<<endl;
    }
    chao.Unlock();//开锁
    }       }
    void thread4_function( )
    { while(sun != 0) 
    {
    chao.Lock(); //锁住 i 。进行判断。
    if (i%7 ==0)
    {
    cout<<"线程4中,i的值"<<i<<"除以7,为整数%%%%%%%%%%%%%%"<<endl;
    }
    chao.Unlock();//开锁
    }       }
    void thread5_function( )
    { while(sun != 0) 
    {
    chao.Lock(); //锁住 i 。进行判断。
    if (i%8 ==0)
    {
    cout<<"线程5中,i的值"<<i<<"除以8,为整数****************"<<endl;
    }
    chao.Unlock();//开锁
    }       }
    void thread6_function( )
    { while(sun != 0) 
    {
    chao.Lock(); //锁住 i 。进行判断。
    if (i%9 ==0)
    {
    cout<<"线程6中,i的值"<<i<<"除以9,为整数(((((((((((((("<<endl;
    }
    chao.Unlock();//开锁
    }       }运行结果 错误。
      

  7.   


    你这么写是不能保证所有工作线程都执行一次后,主线程再 i++。 
    线程的调度,由操作系统分配。线程是调用是无序的,如果你希望所有的子线程都操作完,主线程再实行那就需要用到
    WaitForMultipleObjects(...)函数,等待多有的线程都变成激发态主线程再执行。
      

  8.   

    楼主是不是希望,每一个线程打印出一段文言,然后主线程改变i的值,然后每个线程再执行,一次循环。
    如果是这样的话,目前看楼主的代码是不能实现的。主线程和其他工作线程都会得到CPU的时间,那么当
    主线程打开临界区后,就可以操作i了,但可能还有其他工作线程没有使用过i这个值。当然,也不能保证
    每个工作线程只被调用一次。有个能某一个线程被重复调用,而某几个线程从来都没有得到CPU的时间。举例:
    thread1_function 打印出:cout<<"线程1中,i的值"<<i<<"除以3,为整数@@@@@@@@@@@@"<<endl; 这个之后,只要i 值不变就不在打印了。
    void thread1_function( )
    {
        int old = -1;
        while(sun != 0) 
        {
            if(old != i)
            {  
                chao.Lock();//锁住 i 。进行判断。
                  if (i%3 ==0)
                {
                   cout<<"线程1中,i的值"<<i<<"除以3,为整数@@@@@@@@@@@@"<<endl;
                }
                chao.Unlock();//开锁
                  old = i;
            }
        }       
    }
    这样就能确保,在i值没有变化时,每个工作线程只执行一次。还有一个问题,就是主线程在该边i值的之后怎么才知道 没一个工作线程都打印了呢?
    按照你现在的写法有一个简单的方法。设一个全局变量为计数器。当每一个工作线程打印后,改变这个计数器的值。
    那么主线程,在改变i值的时候,判断一下,这个计数器的值是不是等于工作线程数,如果是,那么就改变i值,如果
    不是,那么说明还有工作线程没有被执行过。放弃改变i值,等待下一次得到CPU时间再说。
    当主线程,进入临界区后,发现这个计数器等于工作线程数了。这时改变i的值,同时再把这个计数器置0。