C语言多线程编程一

1. Windows下同时打开多个对话框:

#include <Windows.h>
#include <process.h>    //创建线程

void runmsg(void *p)
{
    MessageBoxA(0, "hello world", "hello china", 0);

}

void main()
{
    _beginthread(runmsg, 0, NULL);    //启动线程,函数地址,把函数当做线程的入口点
    _beginthread(runmsg, 0, NULL);
    _beginthread(runmsg, 0, NULL);
    _beginthread(runmsg, 0, NULL);

    system("pause");
}

 2. 多线程实现同步和异步:

#include <Windows.h>
#include <stdlib.h>

//typedef unsigned long       DWORD;
//#define WINAPI      __stdcall 标准的呼叫
//typedef void far            *LPVOID;
DWORD WINAPI MyMseg(LPVOID lp)
{
    MessageBoxA(0, "hello", "china", 0);
}
void main() { HANDLE hthread; DWORD threadid; //保存线程编号 //异步执行: //for (int i = 0; i < 5; i++) //{ // hthread = CreateThread( // NULL, //安全属性 // NULL, //堆栈大小 // MyMseg, //线程的入口点 // NULL, //函数的参数 // 0, //立刻执行 // &threadid //保存线程的id // ); //} //多线程实现同步: for (int i = 0; i < 5; i++) { hthread = CreateThread( NULL, //安全属性 NULL, //堆栈大小 MyMseg, //线程的入口点 NULL, //函数的参数 0, //立刻执行 &threadid //保存线程的id ); WaitForSingleObject(hthread, INFINITE); //等待 CloseHandle(hthread); //关闭线程 } system("pause"); }
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <Windows.h>

void run(void *p)
{
    int *px = p;
    printf("线程编号%d\n", *px);
}

void main()
{
    int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    for (int i = 0; i < 10; i++)
    {
        HANDLE hd = (HANDLE) _beginthread(run, 0, &a[i]);    //MyThread线程编号
        WaitForSingleObject(hd, INFINITE);                    //单线程
        //WaitForMultipleObjects()        //多线程
    }

    system("pause");
}

3. 多线程检索:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>      //生成随机数
#include <process.h>

int isfind = 0;        //找到设置为1,其他线程就不再查找

struct findInfo
{
    int *pstart;    //线程检索的首地址
    int length;     //检索的数据长度
    int findNum;    //需要查找的数据 
    int id;         //线程的编号
};

void findIt(void *p)
{
    struct findInfo *ps = p;    //保存地址
    printf("\n线程%d开始查找\n", ps->id);

    //遍历首地址,长度为10个元素
    for (int *pf = ps->pstart; pf < ps->pstart + ps->length; pf++)
    {
        if (isfind == 1)
        {
            printf("线程%d结束查找,其他线程已经找到\n", ps->id);
            return;

        }

        if (*pf == ps->findNum)
        {
            printf("线程%d结束查找,找到数据%d地址%p\n", ps->id, *pf, pf);
            isfind = 1;
            return;
        }

    }

    printf("线程%d结束查找\n", ps->id);

}

void main()
{
    int a[100] = { 0 };
    time_t ts;
    unsigned int data = time(&ts);
    srand(data);    //随机数种子

    for (int i = 0; i < 100; i++)
    {
        a[i] = rand() % 100;
        printf("%4d", a[i]);
        if ((i+1) % 10 == 0)    //每10个打印一行
        {
            printf("\n");
        }
    }

    int num;
    printf("输入要查询的数:\n");
    scanf("%d", &num);

    struct findInfo info[10];    //结构体数组,保存每个线程要查找的信息
    for (int i = 0; i < 10;i++)
    {
        info[i].pstart = a + 10 * i;
        info[i].length = 10;
        info[i].findNum = num;
        info[i].id = i;

        _beginthread(findIt, 0, &info[i]);    //调用线程
    }

    system("pause");
}

 4. 多线程切割:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>        //生成随机数
#include <process.h>

int isfind = 0;        //找到设置为1,其他线程就不再查找

struct findInfo
{
    int *pstart;    //线程检索的首地址
    int length;        //检索的数据长度
    int findNum;    //需要查找的数据 
    int id;            //线程的编号
};

#define M 100    //数据
#define N 8        //线程数量

void findIt(void *p)
{
    struct findInfo *ps = p;    //保存地址
    printf("\n线程%d开始查找\n", ps->id);

    //遍历首地址,长度为10个元素
    for (int *pf = ps->pstart; pf < ps->pstart + ps->length; pf++)
    {
        if (isfind == 1)
        {
            printf("线程%d结束查找,其他线程已经找到\n", ps->id);
            return;

        }

        if (*pf == ps->findNum)
        {
            printf("线程%d结束查找,找到数据%d地址%p\n", ps->id, *pf, pf);
            isfind = 1;
            return;
        }
    }

    printf("线程%d结束查找\n", ps->id);
}

void main()
{
    int a[100] = { 0 };
    time_t ts;
    unsigned int data = time(&ts);
    srand(data);    //随机数种子

    for (int i = 0; i < 100; i++)
    {
        a[i] = rand() % 100;
        printf("%4d", a[i]);
        if ((i+1) % 10 == 0)    //每10个打印一行
        {
            printf("\n");
        }
    }

    int num;
    printf("输入要查询的数:\n");
    scanf("%d", &num);

    struct findInfo info[N];    //结构体数组,保存每个线程要查找的信息
    if (M%N == 0)    //前面能整除的情况
    {
        for (int i = 0; i < N; i++)
        {
            info[i].pstart = a + M/N * i;
            info[i].length = M/N;
            info[i].findNum = num;
            info[i].id = i;
            HANDLE hd = _beginthread(findIt, 0, &info[i]);
        }
    }
    else            //不能整除的情况
    {
        for (int i = 0; i < N-1; i++)
        {
            info[i].pstart = a + M / (N-1) * i;
            info[i].length = M / (N - 1);
            info[i].findNum = num;
            info[i].id = i;
            HANDLE hd = _beginthread(findIt, 0, &info[i]);
        }
        //info[N-1];
        int i = N - 1;
        info[i].pstart = a + M / (N - 1) * i;
        info[i].length = M % (N - 1);
        info[i].findNum = num;
        info[i].id = i;
        HANDLE hd = _beginthread(findIt, 0, &info[i]);
    }

    system("pause");
}

 5. 多线程冲突:

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <Windows.h>
#include <time.h>

CRITICAL_SECTION cs;    //临界区,全局

int num = 0;            //全局变量,多线程同时访问会发生冲突

//10 *     100 * 100
DWORD WINAPI myfun(void *p)
{
    for (int i = 0; i < 100; i++)
    {
        EnterCriticalSection(&cs);    //进入临界区
        num++;
        LeaveCriticalSection(&cs);    //离开临界区
        //Sleep(10);
    }
    return 0;
}

void main()
{
    time_t start, end;
    time(&start);

    HANDLE hd[100];
    for (int i = 0; i < 100; i++)
    {
        hd[i] = CreateThread(NULL, 0, myfun, NULL, 0, NULL);
        //hd[i] = _beginthread(myfun, 0, NULL);    //线程数组,数组的每一个元素都是一个线程
        //WaitForSingleObject(hd[i], INFINITE);    //等待单个的线程结束(同步)
    }
    WaitForMultipleObjects(100, hd, TRUE, INFINITE);    //等待所有线程退出
    
    time(&end);
    printf("%f\n", difftime(end, start));

    printf("%d\n", num);
    
    DeleteCriticalSection(&cs);
    system("pause");
}

6. 多线程的操作:

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <Windows.h>

//_beginthread CreateThread 创建线程
//_endthread ExitThread 内部结束线程   TerminateThread 外部强制结束
//SuspendThread冻结    ResumeThread解冻     

DWORD WINAPI fun(void *p)
{
    int i = 0;
    while (++i)
    {
        printf("%d\n", i);

        if (i > 8000)
        {
            //_endthread();    //用于线程内部退出
            ExitThread(0);    //同上
        }

    }


    return 0;
}

//主线程,主导作用,管理调度其他线程
void main()
{
    HANDLE hd = CreateThread(NULL, 0, fun, NULL, 0, NULL);

    system("pause");
    SuspendThread(hd);    //冻结线程
    system("pause");
    ResumeThread(hd);    //解冻线程
    system("pause");

    
    TerminateThread(hd,0);    //外部强行结束线程

    system("pause");
}

7. 临界区 Critical Section:

#include <stdio.h>
#include <stdlib.h>
#include <process.h>
#include <Windows.h>

#define N 10    //#define N 100 临界区最大线程是64
int num = 0;

CRITICAL_SECTION cs1;    //定义临界区,为结构体变量
CRITICAL_SECTION cs2;

DWORD WINAPI add(void *p)
{
    EnterCriticalSection(&cs1);    //进入临界区,写在for循环外,节省了在循环中反复进入和退出临界区
    for (int i = 0; i < 10000; i++)
    {
        //EnterCriticalSection(&cs1);    
        num++;
        //LeaveCriticalSection(&cs1);    
    }
    LeaveCriticalSection(&cs1);    //退出临界区

    return 0;
}

DWORD WINAPI sub(void *p)
{
    EnterCriticalSection(&cs2);    //进入临界区,写在for循环外,节省了在循环中反复进入和退出临界区
    for (int i = 0; i < 10000; i++)
    {
        num--;    
    }
    LeaveCriticalSection(&cs2);    //退出临界区

    return 0;
}

void main()
{
    InitializeCriticalSection(&cs1);    //初始化临界区结构体
    InitializeCriticalSection(&cs2);

    {
        HANDLE hd[N];
        for (int i = 0; i < N; i++)
        {
            hd[i] = CreateThread(NULL, 0, add, NULL, 0, NULL);    //创建线程
            //WaitForSingleObject(hd[i], INFINITE);
        }
        WaitForMultipleObjects(N, hd, TRUE, INFINITE);    //等待全部线程退出

        printf("num=%d\n", num);
    }

    {
        HANDLE hd[N];
        for (int i = 0; i < N; i++)
        {
            hd[i] = CreateThread(NULL, 0, sub, NULL, 0, NULL);    //创建线程
            //WaitForSingleObject(hd[i], INFINITE);
        }
        WaitForMultipleObjects(N, hd, TRUE, INFINITE);    //等待全部线程退出

        printf("num=%d\n", num);
    }

    DeleteCriticalSection(&cs1);    //释放临界区
    DeleteCriticalSection(&cs2);

    system("pause");
}

 8. 线程通信-事件机制 event:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

HANDLE event[3] = {0};    //事件
HANDLE hd[3] = { 0 };    //线程数组

DWORD WINAPI firstthread(void *p)
{
    MessageBoxA(0, "1", "1", 0);
    printf("第1个线程执行完成.\n");

    SetEvent(event[0]);                            //设置event信号
    return 0;
}

DWORD WINAPI secondthread(void *p)
{
    WaitForSingleObject(event[0], INFINITE);    //等待event信号出现,才执行下一步
    
    MessageBoxA(0, "2", "2", 0);

    printf("第2个线程执行完成.\n");
    return 0;
}

void main()
{
    event[0] = CreateEvent(NULL, TRUE, FALSE, NULL);    //创建事件
    event[1] = CreateEvent(NULL, TRUE, FALSE, NULL);

    hd[0] = CreateThread(NULL, 0, firstthread, NULL, 0, NULL);    //创建线程
    hd[1] = CreateThread(NULL, 0, secondthread, NULL, 0, NULL);

    WaitForMultipleObjects(2, hd, TRUE, INFINITE);
    printf("全部完成!\n");

    system("pause");
}
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <memory.h>

HANDLE event[4] = { 0 };    //事件
HANDLE hd[3] = { 0 };        //线程数组
char str[1024] = { 0 };        //代表聊天内容的缓冲区

CRITICAL_SECTION(cs);        //临界区

//0  张通知媒婆
//1  媒婆发给李
//2  李通知媒婆
//3  媒婆发给张
DWORD WINAPI Zhang(void *p)
{
    int i = 1;

    EnterCriticalSection(&cs);    //进入临界区
    memset(str, '\0', 1024);
    sprintf(str, "张第%d次说:I love you Li\n", i);
    LeaveCriticalSection(&cs);    //离开临界区

    Sleep(1000);
    SetEvent(event[0]);
    
    while (++i)
    {
        WaitForSingleObject(event[3], INFINITE);

        EnterCriticalSection(&cs);    //进入临界区
        memset(str, '\0', 1024);
        sprintf(str, "张第%d次说:I love you Li\n", i);
        LeaveCriticalSection(&cs);    //离开临界区

        Sleep(1000);
        SetEvent(event[0]);
        
    }

    return 0;
}

DWORD WINAPI Li(void *p)
{
    int i = 0;
    while (++i)
    {
        WaitForSingleObject(event[1], INFINITE);

        EnterCriticalSection(&cs);    //进入临界区
        memset(str, '\0', 1024);
        sprintf(str,"李第%d次说:I love you too\n", i);
        LeaveCriticalSection(&cs);    //离开临界区

        Sleep(1000);
        SetEvent(event[2]);
        
    }

    return 0;
}

DWORD WINAPI show(void *p)
{
    int i = 0;
    while (++i)
    {
        WaitForSingleObject(event[0], INFINITE);

        EnterCriticalSection(&cs);    //进入临界区
        printf("媒婆传递:%s\n", str);
        LeaveCriticalSection(&cs);    //离开临界区

        Sleep(1000);
        SetEvent(event[1]);


        WaitForSingleObject(event[2], INFINITE);
        EnterCriticalSection(&cs);
        printf("媒婆传递:%s\n", str);
        LeaveCriticalSection(&cs);
        
        Sleep(1000);
        SetEvent(event[3]);
    }

    return 0;
}


void main()
{
    InitializeCriticalSection(&cs);

    event[0] = CreateEvent(NULL, TRUE, FALSE, NULL);    //创建事件
    event[1] = CreateEvent(NULL, TRUE, FALSE, NULL);
    event[2] = CreateEvent(NULL, TRUE, FALSE, NULL);
    event[3] = CreateEvent(NULL, TRUE, FALSE, NULL);

    hd[0] = CreateThread(NULL, 0, Zhang, NULL, 0, NULL);    //创建线程
    hd[1] = CreateThread(NULL, 0, Li, NULL, 0, NULL);
    hd[2] = CreateThread(NULL, 0, show, NULL, 0, NULL);

    WaitForMultipleObjects(2, hd, TRUE, INFINITE);
    printf("全部完成!\n");

    DeleteCriticalSection(&cs);

    system("pause");
}

9. 线程互斥量 mutex:

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

int num = 0;

HANDLE mutex = NULL;    //指针

DWORD WINAPI add(void *p)
{
    WaitForSingleObject(mutex, INFINITE);
    for (int i = 0; i < 100000; i++)
    {
        num++;
    }
    ReleaseMutex(mutex);

    return 0;
}

void main()
{
    mutex = CreateMutex(NULL, FALSE, NULL);    //创建互斥量
    if (mutex == NULL)
    {
        //创建失败
    }
        
    HANDLE hd[10];    //线程互斥,同一个互斥量只能解决64个线程

    for (int i = 0; i < 10; i++)    //创建10个线程
    {
        hd[i] = CreateThread(NULL, 0, add, NULL, 0, NULL);
        if (mutex == NULL)
        {
            //创建失败
        }    
    }

    WaitForMultipleObjects(10, hd, TRUE, INFINITE);

    printf("%d\n", num);

    for (int i = 0; i < 10; i++)    //关闭每一个线程资源
    {
        CloseHandle(hd[i]);
    }

    CloseHandle(mutex);        //关闭互斥量

    system("pause");
}

 10. 原子变量 valatile :

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <Windows.h>

void main0401()
{
    //release 优化
    //volatile 原子操作 强制读内存 不考虑副本
    for (volatile int i = 0; i < INT_MAX; i++)
    {

    }

    printf("over");
    system("pause");
}

volatile int num = 20;        //现代编译器做了优化,加不加volatile是一样的

DWORD WINAPI msg(void *p)    //
{
    int *px = (int *)p;

    while (1)
    {
        int data = *px;            //强制读内存
        printf("%d\n", data);

        Sleep(1000);
    }
}

DWORD WINAPI cmsg(void *p)    //
{
    int *px = (int *)p;

    while (1)
    {

        *px += 1;

        Sleep(10000);
    }
}

void main()
{
    CreateThread(NULL, 0, msg, &num, 0, NULL);
    CreateThread(NULL, 0, cmsg, &num, 0, NULL);

    printf("over");
    system("pause");
}
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <Windows.h>

int num = 0;    //多个线程同时访问一个变量会发生冲突,同时写入
//线程安全:一个变量是线程安全,多线程同时读写没有误差
//临界区(Critical Section)、事件机制(event)、互斥量(Mutex) 
//原子操作的速度要快于 临界区(Critical Section)、事件机制(event)、互斥量(Mutex) 
DWORD WINAPI runX(void *p)    
{
    for (int i = 0; i < 10000; i++)
    {
        //num++;
        InterlockedIncrement(&num);    //num++保证是完整操作,我操作完成了后续才能继续执行
    }

    return 0;
}

void main()
{
    HANDLE hd[50];
    for (int i = 0; i < 50; i++)
    {
        hd[i] = CreateThread(NULL, 0, runX, NULL, 0, NULL);
    }
    WaitForMultipleObjects(50, hd, TRUE, INFINITE);

    printf("%d\n", num);

    system("pause");
}

 11. 定时器 timer :

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>

//单独定时器只能用于同步通信
void main0601()
{
    HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL);    //创建定时器
    if (timer == NULL)
    {
        return;
    }

    LARGE_INTEGER time;            //
    time.QuadPart = -20000000;    //2秒
    //单位是10^-7秒  0.1微秒
    SetWaitableTimer(timer, &time, 0, NULL, 0, NULL);    //设置定时器等待2秒

    if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0)
    {
        printf("等待成功!\n");
    }
    else
    {
        printf("等待失败!\n");
    }

    system("pause");
}

HANDLE timer;

DWORD WINAPI go1(void *p)
{
    MessageBoxA(0, "1", "1", 0);

    timer = CreateWaitableTimer(NULL, TRUE, NULL);    //创建定时器
    LARGE_INTEGER time;            //
    time.QuadPart = -50000000;    //2秒
                                //单位是10^-7秒  0.1微秒
    SetWaitableTimer(timer, &time, 0, NULL, 0, NULL);    //设置定时器等待2秒
}

DWORD WINAPI go2(void *p)
{
    WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0;
    MessageBoxA(0, "2", "2", 0);
    printf("等待成功!\n");
}

void main()
{
    HANDLE hd = CreateThread(NULL, 0, go1, NULL, 0, NULL);

    WaitForSingleObject(hd, INFINITE);

    if (WaitForSingleObject(timer, INFINITE) == WAIT_OBJECT_0)
    {
        CreateThread(NULL, 0, go2, NULL, 0, NULL);
        printf("等待成功!\n");
    }
    else
    {
        printf("等待失败!\n");
    }

    system("pause");
}

 

posted @ 2018-08-19 20:03  博观&约取  阅读(1636)  评论(0编辑  收藏  举报