码迷,mamicode.com
首页 > 编程语言 > 详细

线程同步

时间:2018-02-05 00:39:30      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:idt   class   let   代码   --   handle   this   ram   cstring   

今天要写的小程序是卖票

结果如下:共100张票,10个线程

技术分享图片

需要声明的一些变量:

public:
    volatile int m_tickets;//原子访问
     static unsigned __stdcall  ThreadProc(void* lparam);
     CListBox m_lstbox;
     map<unsigned int , int> IDMap;//将线程ID和0~10对应
     bool m_flag;
     CRITICAL_SECTION  m_cs;//临界区
     HANDLE m_Mutex;//互斥量

按钮的处理函数:

void CSoldTicketDlg::OnBnClickedButton1()
{
    unsigned int IDnum;
    for(int i = 0; i < 10; i++)
    {
        _beginthreadex(NULL,0,&ThreadProc,this,0,&IDnum);
        IDMap[IDnum] = i;
    }
}

 

线程同步有三种方式:

一 . 原子访问:指的是一个线程在访问某个资源的同时,能够保证没有其他线程会在同一时刻访问同一资源。Interlocked系列。

volatile,:防止编译优化(从寄存器中取值,相对于从外存取值更节省时间,但造成了不能取到的值不能及时更新),对特殊地址的稳定访问。

缺点:只能实现对一个32位或者64位值的单独访问,不能实现复杂的功能。

二 . 关键段(临界区):同一时刻只一个线程访问代码段

1.普通锁

IniticalizeCriticalsection(&g_cs); //初始化CRITICAL_SECTION 中的成员变量

EnterCriticalSection(&g_cs); //线程用它来检查占用标志的函数

LeaveCriticalSection(&g_cs); //离开“卫生间”,门上重新置为无人

DeleteCriticalsection(&g_cs); //删除事件的内核对象,以及为CRITICAL_SECTION初始化的资源。

初始化函数:InitializeCriticalSection(&m_cs);

在Destroy函数中:

void CSoldTicketDlg::OnDestroy()
{
    
    CDialogEx::OnDestroy();
    DeleteCriticalSection(&m_cs);
    
}

线程执行的函数:

 unsigned __stdcall  CSoldTicketDlg::ThreadProc(void* lparam)
 {
    CSoldTicketDlg* pthis = (CSoldTicketDlg*)lparam;
    int num = pthis->IDMap[GetCurrentThreadId()];
    while(1)
    {
        if(pthis->m_tickets <= 0 )
            break;
        Sleep(100);
        CString str;
         EnterCriticalSection(&pthis->m_cs);//锁住
        if(pthis->m_tickets > 0)//解决负数问题
        {
            str.Format(_T("第%d窗口,卖出第%d张票"),num , pthis->m_tickets--);
        } 
        LeaveCriticalSection(&pthis->m_cs);
        pthis->m_lstbox.AddString(str);
    }
    return 0;

 }

 

2.旋转锁:

InitializeCriticalSectionAndSpinCount:旋转锁不断循环,尝试在一段时间内获得访问权。只有当尝试失败的时候,线程才会切换到内核模式并进入等待状态。

SetCriticalSectionSpinCount(   //改变旋转锁的次数

在初始化函数中:InitializeCriticalSectionAndSpinCount(&m_cs,1);

3.异步

TryEnterCriticalSection:线程在访问时,如果不能访问资源,那么它继续做其他事情,而不用等待。

将EnterCriticalSection换为

if(!TryEnterCriticalSection(&pthis->m_cs))//异步
continue;

三 . 互斥量

初始化函数:m_Mutex = CreateMutex(0,FALSE,0);//第二个参数为创建互斥量的进程没有优先级

 unsigned __stdcall  CSoldTicketDlg::ThreadProc(void* lparam)
 {
    CSoldTicketDlg* pthis = (CSoldTicketDlg*)lparam;
    int num = pthis->IDMap[GetCurrentThreadId()];
    while(1)
    {
        if(pthis->m_tickets <= 0 )
            break;
        Sleep(100);
        CString str;
        if(WAIT_TIMEOUT == WaitForSingleObject(pthis->m_Mutex,50))
             continue;
        if(pthis->m_tickets > 0)//解决负数问题
        {
            str.Format(_T("第%d窗口,卖出第%d张票"),num , pthis->m_tickets--);
        } 
        ReleaseMutex(pthis->m_Mutex);
        pthis->m_lstbox.AddString(str);
    }
    return 0;

 }

 

线程同步

标签:idt   class   let   代码   --   handle   this   ram   cstring   

原文地址:https://www.cnblogs.com/Lune-Qiu/p/8414652.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!