精华内容
下载资源
问答
  • 线程之间的通信可以有效的利用资源,让线程之间的活动尽然有序,在线程之间的通信常用的方法: 对象锁.wait();//让线程进入等待Block状态 对象锁.notify();//唤醒Block中的线程 对象锁.notifyAll();//唤醒所有的...

    等待与唤醒机制
    线程之间的通信可以有效的利用资源,让线程之间的活动尽然有序,在线程之间的通信常用的方法有:

    对象锁.wait();//让线程进入等待Block状态
    对象锁.notify();//唤醒Block中的线程
    对象锁.notifyAll();//唤醒所有的线程
    

    注意事项:wait和notify方法只能用于同一个对象锁,用在同步代码块中,同步方法中,写在同步代码块中。

    展开全文
  • 线程之间的同步 1 为什么要线程之间进行同步 当有多个线程同时对某一块资源进行读写的时候就会发生冲突,例如个线程都尝试改变一个变量的值,最终会导致数据计算的出错,也即线程竞争 简单讲: 两个程序同时读写同一...

    线程之间的同步

    1 为什么要线程之间进行同步

    • 当有多个线程同时对某一块资源进行读写的时候就会发生冲突,例如多个线程都尝试改变一个变量的值,最终会导致数据计算的出错,也即线程竞争
    • 简单讲: 两个程序同时读写同一个共享数据时会发生意想不到的后果
    • 为了避免这种情况,必须要在程序中采取同步的机制

    2 线程之间的5种常用同步方式(本文简要介绍前三种)

    2.1 原子互锁家族的函数
    • 我们把单指令的操作称为原子的

    • 当我们调用原子操作时,因为其实单条指令形式,所以不会被打断

    • Win API中有一个原子操作的函数族如下所示

    // 加1操作
    InterlockedIncrement
    // 减1操作
    InterlockedDecrement
    // 加上“指定”的值,可以加上一个负数
    InterlockedExchangeAdd
    // 能够以原子操作的方式用第二个参数的值来取代第一个参数的值
    InterlockedExchange
    InterlockedExchangePointer
    
    • 但是因为这些原子操作都是比较简单指令,只能完成比较简单的操作,当遇到复杂情况时,就需要用到其他的技术了: 比如
    2.2 关键代码段 Critical Sections
    • 关键代码段又称为临界区等,是一种比互斥器更加严格的同步手段
    • 用户模式对象, 不是系统核心对象
    • 使用方法如下:
    0.	先创建一个临界区结构体	CRITICAL_SECTION CriticalSection;
    1.	初始化	   InitializeCriticalSection;
    2.	进入	 	EnterCriticalSection;
    3.	尝试进入  TryEnterCriticalSection;
    4.	离开		LeaveCriticalSection;
    5.	删除		DeleteCriticalSection;
    
    • 特点:
    // 因为不是核心对象,所以执行速度快,有效率;
    // 因为不是核心对象,所以不能跨进程使用;
    // 可以多次进入,但是也必须多次退出
    // 最好不要同时进入或等待多个Critical Sections,容易造成死锁
    // 无法检测到进入到Critical Sections里面的线程是否已经退出!
    // 也即是说:如果某个进入Critical Sections的线程已经退出但是没有主动离开Critical Sections,外边处于等待状态的线程就会一直等待,因为不知道里面的线程已经退出了
    
    • MFC中也可以应用关键代码段有封装好的类: CCriticalSection
    2.3 Mutex 互斥器
    • 系统核心对象
    • 使用方法:
    1.	创建一个互斥器:	CreatMutex
    2.	打开一个已经存在的互斥器:	OpenMutex
    3.	获得互斥器的拥有权:	WaitForSingleObject、WaitForMutipleObject 等一类函数
    4.	释放互斥器:	ReleaseMutex
    5.	关闭互斥器:	CloseHandle
    
    • 示例代码:
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    
    // This process creates the mutex object.
    // 在第一个进程中创建Mutex,然后并没有拥有其所有权
    // 等待第二个进程
    int main(void)
    {
        HANDLE hMutex; 
    
        hMutex = CreateMutex( 
            NULL,                        // default security descriptor
            FALSE,                       // mutex not owned
            TEXT("NameOfMutexObject"));  // object name
    
        if (hMutex == NULL) 
            printf("CreateMutex error: %d\n", GetLastError() ); 
        else 
            if ( GetLastError() == ERROR_ALREADY_EXISTS ) 
                printf("CreateMutex opened an existing mutex\n"); 
            else printf("CreateMutex created a new mutex.\n");
    
        // Keep this process around until the second process is run
        _getch();
    
        CloseHandle(hMutex);
    
        return 0;
    }
    // 节选自微软官网
    
    #include <windows.h>
    #include <stdio.h>
    
    // This process opens a handle to a mutex created by another process.
    // 该进程打开一个已存在的Mutex
    int main(void)
    {
        HANDLE hMutex; 
    
        hMutex = OpenMutex( 
            MUTEX_ALL_ACCESS,            // request full access
            FALSE,                       // handle not inheritable
            TEXT("NameOfMutexObject"));  // object name
    
        if (hMutex == NULL) 
            printf("OpenMutex error: %d\n", GetLastError() );
        else printf("OpenMutex successfully opened the mutex.\n");
    
        CloseHandle(hMutex);
    
        return 0;
        // 节选自微软官网
    }
    
    • 只有打开或一个新的Mutex之后才可以进入并使用该锁
    • 特点:
    // 系统核心对象的共同特征:需要有安全描述指针,用完后要CloseHandle关闭句柄,可以跨进程使用
    // Mutex可以跨进程使用,所以其名称对整个系统而言是全局的,所以命名不要过于普通,最好想一些独一无二的名字等
    // 因为是核心对象,所以访问速度相比用户对象要慢100倍左右
    // Mutex使用正确时,一般不会发生死锁
    // 在"等待"一个Mutex的时候,可以指定"结束等待"的时间长度
    // 可以检测到当前拥有互斥器所有权的线程是否已经退出!如果已经退出-----Wait...函数会返回: WAIT_ABANDONED
    
    • WaitForSingleObject()函数的返回值
    // 出现在互斥锁的情况,表示拥有该锁的线程已经结束了,但是没有释放该锁 
    WAIT_ABANDONED			//(是Mutex时特有的情况)
        
    // 等待的对象处于有信号状态
    WAIT_OBJECT_0
        
    // 等待超时
    WAIT_TIMEOUT
        
    // 函数执行失败,可以GetLastError()
    WAIT_FAILED
    

    3 Win中的核心对象

    Windows核心对象一览

    展开全文
  • 在windows编程中互斥器mutex的作用和临界区critiacl sectin类似,请说...答:最常用的进程间的通信方式信号、信号量、消息队列、共享内存。 概念: 进程:一个程序在一次数据集合上的运行,所以一个程序在不同...

     

    在windows编程中互斥器mutex的作用和临界区critiacl sectin类似,请说一下两者间的主要区别。

    答:多线程编程问题。主要是mutex可以用于进程间的互斥,critical section是线程之间的互斥。

    进程间的通信是如何实现的?

    答:最常用的进程间的通信方式有信号、信号量、消息队列、共享内存。

    概念:

    进程:一个程序在一次数据集合上的运行,所以一个程序在不同数据集合上运行,乃至一个程序在同样数据集合上多次运行都是不同的进程。

    线程:线程是进程中的一个实体,被系统独立调度和执行的基本单位。

    管程:实际上是定义可一个数据结构和在该数据结构上能为并发进程所执行的一组操作,这组操作能同步进程和改变管程中的数据。

    以下内容:

    转载   iWan http://www.cnblogs.com/memewry/archive/2012/08/22/2651696.html

    进程/线程同步的方式和机制,进程间通信

    一、进程/线程间同步机制。

    临界区、互斥区、事件、信号量四种方式 临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别

    1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。

    2、互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享 .互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。

    3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目 .信号量对象对线程的同步方式与前面几种方法不同,信号允许多个线程同时使用共享资源,这与操作系统中的PV操作相同。它指出了同时访问共享资源的线程最大数目。它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。

    PV操作及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量S是一个整数,S大于等于零时代表可供并发进程使用的资源实体数,但S小于零时则表示正在等待使用共享资源的进程数。   

    P操作申请资源:  

     (1)S减1;  

     (2)若S减1后仍大于等于零,则进程继续执行;  

     (3)若S减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转入进程调度。   

      V操作 释放资源:  

     (1)S加1;  

     (2)若相加结果大于零,则进程继续执行;  

     (3)若相加结果小于等于零,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转入进程调度。

    4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作 .

     

    总结:   

    1. 互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量。因为互斥量是跨进程的互斥量一旦被创建,就可以通过名字打开它。   

    2. 互斥量(Mutex),信号灯(Semaphore),事件(Event)都可以被跨越进程使用来进行同步数据操作,而其他的对象与数据同步操作无关,但对于进程和线程来讲,如果进程和线程在运行状态则为无信号状态,在退出后为有信号状态。所以可以使用WaitForSingleObject来等待进程和线程退出。  

     3. 通过互斥量可以指定资源被独占的方式使用,但如果有下面一种情况通过互斥量就无法处理,比如现在一位用户购买了一份三个并发访问许可的数据库系统,可以根据用户购买的访问许可数量来决定有多少个线程/进程能同时进行数据库操作,这时候如果利用互斥量就没有办法完成这个要求,信号灯对象可以说是一种资源计数器。

     

    二、进程间通信方式

    由于比较容易混淆,我们把进程间通信方法也列在这里做比较。

    程间通信就是在不同进程之间传播或交换信息,那么不同进程之间存在着什么双方都可以访问的介质呢?进程的用户空间是互相独立的,一般而言是不能互相访问的,唯一的例外是共享内存区。但是,系统空间却是“公共场所”,所以内核显然可以提供这样的条件。除此以外,那就是双方都可以访问的外设了。在这个意义上,两个进程当然也可以通过磁盘上的普通文件交换信息,或者通过“注册表”或其它数据库中的某些表项和记录交换信息。广义上这也是进程间通信的手段,但是一般都不把这算作“进程间通信”。因为那些通信手段的效率太低了,而人们对进程间通信的要求是要有一定的实时性。

     

      进程间通信主要包括管道, 系统IPC(包括消息队列,信号量,共享存储), SOCKET.

        管道分为有名管道和无名管道,无名管道只能用于亲属进程之间的通信,而有名管道则可用于无亲属关系的进程之间。

        消息队列用于运行于同一台机器上的进程间通信,与管道相似;

      共享内存通常由一个进程创建,其余进程对这块内存区进行读写。得到共享内存有两种方式:映射/dev/mem设备和内存映像文件。前一种方式不给系统带来额外的开销,但在现实中并不常用,因为它控制存取的是实际的物理内存;

         本质上,信号量是一个计数器,它用来记录对某个资源(如共享内存)的存取状况。一般说来,为了获得共享资源,进程需要执行下列操作:

      (1)测试控制该资源的信号量;

      (2)若此信号量的值为正,则允许进行使用该资源,进程将进号量减1;

      (3)若此信号量为0,则该资源目前不可用,进程进入睡眠状态,直至信号量值大于0,进程被唤醒,转入步骤(1);

      (4)当进程不再使用一个信号量控制的资源时,信号量值加1,如果此时有进程正在睡眠等待此信号量,则唤醒此进程。     套接字通信并不为Linux所专有,在所有提供了TCP/IP协议栈的操作系统中几乎都提供了socket,而所有这样操作系统,对套接字的编程方法几乎是完全一样的

     

    三、进程/线程同步机制与进程间通信机制比较

    很明显2者有类似,但是差别很大

    同步主要是临界区、互斥、信号量、事件

    进程间通信是管道、内存共享、消息队列、信号量、socket

    共通之处是,信号量和消息(事件)

     

    其他资料:

    进程间通讯(IPC)方法主要有以下几种:        管道/FIFO/共享内存/消息队列/信号   

    1.管道中还有命名管道和非命名管道(即匿名管道)之分,非命名管道(即匿名管道)只能用于父子进程通讯,命名管道可用于非父子进程,命名管道就是FIFO,管道是先进先出的通讯方式    

    2.消息队列是用于两个进程之间的通讯,首先在一个进程中创建一个消息队列,然后再往消息队列中写数据,而另一个进程则从那个消息队列中取数据。需要注意的是,消息队列是用创建文件的方式建立的,如果一个进程向某个消息队列中写入了数据之后,另一个进程并没有取出数据,即使向消息队列中写数据的进程已经结束,保存在消息队列中的数据并没有消失,也就是说下次再从这个消息队列读数据的时候,就是上次的数据!!!!    

    3.信号量,它与WINDOWS下的信号量是一样的,所以就不用多说了    

    4.共享内存,类似于WINDOWS下的DLL中的共享变量,但LINUX下的共享内存区不需要像DLL这样的东西,只要首先创建一个共享内存区,其它进程按照一定的步骤就能访问到这个共享内存区中的数据,当然可读可写      

    以上几种方式的比较:    

    1.管道:速度慢,容量有限,只有父子进程能通讯    

    2.FIFO:任何进程间都能通讯,但速度慢    

    3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题    

    4.信号量:不能传递复杂消息,只能用来同步    

    5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存

     

     

    转载于:https://www.cnblogs.com/jiawang/p/4750262.html

    展开全文
  • 同步机制及windows同步函数使用

    千次阅读 2008-11-06 10:17:00
    【转】同步机制及windows同步函数的使用作者:simahao原文链接:...最近由于使用多线程,不可避免的要用到线程之间的同步,对一些常用的windows 中同步函数和机制有了一些初步的了解,并且写了一些小例子

    【转】同步机制及windows同步函数的使用

    作者:simahao

    原文链接:http://blog.csdn.net/simahao/archive/2005/07/15/425420.aspx

     

    本篇文章适合比较熟悉多线程并且想学习线程同步的读者。

    最近由于使用多线程,不可避免的要用到线程之间的同步,对一些常用的windows 中同步函数和机制有了一些初步的了解,并且写了一些小例子来验证,当然其中难免有错误和疏漏之处,希望高手能给我这个小鸟指出不足之处,非常感谢。

    目录
    一 临界区
    二 互斥体
    三 事件
    四 信号量
    五  附录

     

    一 临界区

    临界区的使用在线程同步中应该算是比较简单,说它简单还是说它同后面讲到的其它方法相比更容易理解。举个简单的例子:比如说有一个全局变量(公共资源)两个线程都会对它进行写操作和读操作,如果我们在这里不加以控制,会产生意想不到的结果。假设线程A正在把全局变量加1然后打印在屏幕上,但是这时切换到线程B,线程B又把全局变量加1然后又切换到线程A,这时候线程A打印的结果就不是程序想要的结果,也就产生了错误。解决的办法就是设置一个区域,让线程A在操纵全局变量的时候进行加锁,线程B如果想操纵这个全局变量就要等待线程A释放这个锁,这个也就是临界区的概念。


    使用方法:
    CRITICAL_SECTION cs;
    InitializeCriticalSection(&cs);
    EnterCriticalSection(&cs);
    ...
    LeaveCriticalSection(&cs);
    DeleteCriticalSection(&cs);
    #include "stdafx.h"
    #include <windows.h>
    #include <process.h>
    #include <iostream>
    using namespace std;

    /****************************************************************
    *在使用临界区的时候要注意,每一个共享资源就有一个CRITICAL_SECTION
    *如果要一次访问多个共享变量,各个线程要保证访问的顺序一致,如果不
    *一致,很可能发生死锁。例如:
    *   thread one:
    *   EnterCriticalSection(&c1)
    *   EnterCriticalSection(&c2)
    *   ...
    *   Leave...
    *   Leave...
    *
    *   thread two:
    *   EnterCriticalSection(&c2);
    *   EnterCriticalSection(&c1);
    *   ...
    *   Leave...
    *   Leave...
    *这样的情况就会发生死锁,应该让线程2进入临界区的顺序同线程1相同
    ****************************************************************/

    const int MAX_THREADNUMS = 4;            //产生线程数目
    CRITICAL_SECTION cs;                             //临界区
    HANDLE event[MAX_THREADNUMS];       //保存createevent的返回handle
    int critical_value = 0;                                   //共享资源

    UINT WINAPI ThreadFunc(void* arg)
    {
        int thread = (int)arg;
        for (int i = 0; i < 5; i++)
        {   
            EnterCriticalSection(&cs);
            cout << "thread " << thread << " ";

            critical_value++;
            cout << "critical_value = " << critical_value << endl;    
            LeaveCriticalSection(&cs);
        }
        SetEvent(event[thread]);
        return 1;
    }

    int main(int argc, char* argv[])
    {
        cout << "this is a critical_section test program" << endl;
        HANDLE hThread;
        UINT uThreadID;
        DWORD dwWaitRet = 0;
     
        InitializeCriticalSection(&cs);

        for (int i = 0; i < MAX_THREADNUMS; i++)
        {
            event[i] = CreateEvent(NULL, TRUE, FALSE, "");
            if (event[i] == NULL)
            {
                cout << "create event " << i << " failed with code: "
                    << GetLastError() << endl;
                continue;
            }
            hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc,
                (void*)i, 0, &uThreadID);
            if (hThread == 0)
            {
                cout << "begin thread " << i << " failed with code: "
                    << GetLastError() << endl;
                continue;
            }
            CloseHandle(hThread);
        }
        //等待所有线程完成
        dwWaitRet = WaitForMultipleObjects(MAX_THREADNUMS, event, TRUE, INFINITE);
        switch(dwWaitRet)
        {
        case WAIT_OBJECT_0:             

            cout << "all the sub thread has exit!" << endl;
            break;
        default:
            cout << "wait for all the thread failed with code:" << GetLastError() << endl;
            break;
        }
       
        DeleteCriticalSection(&cs);
        for (int k = 0; k < MAX_THREADNUMS; k++)
        {
            CloseHandle(event[k]);
        }
     return 0;
    }

     

    二 互斥体
    windows api中提供了一个互斥体,功能上要比临界区强大。也许你要问,这个东东和临界区有什么区别
    ,为什么强大?它们有以下几点不一致:
    1.critical section是局部对象,而mutex是核心对象。因此像waitforsingleobject是不可以等待临界区的。
    2.critical section是快速高效的,而mutex同其相比要慢很多
    3.critical section使用范围是单一进程中的各个线程,而mutex由于可以有一个名字,因此它是可以应用
    于不同的进程,当然也可以应用于同一个进程中的不同线程。
    4.critical section 无法检测到是否被某一个线程释放,而mutex在某一个线程结束之后会产生一
    个abandoned的信息。同时mutex只能被拥有它的线程释放。下面举两个应用mutex的例子,一个是程序只能运行一个实例,也就是说同一个程序如果已经运行了,就不能再运行了;另一个是关于非常经典的哲学家吃饭问题的例子。


     

    程序运行单个实例:
    #include "stdafx.h"
    #include <windows.h>
    #include <process.h>
    #include <iostream>
    using namespace std;

    //当输入s或者c时候结束程序
    void PrintInfo(HANDLE& h, char t)
    {
        char c;
        while (1)
        {
            cin >> c;
            if (c == t)
            {
                ReleaseMutex(h);
                CloseHandle(h);
                break;
            }
            Sleep(100);
        }
    }
    int main(int argc, char* argv[])
    {
        //创建mutex,当已经程序发现已经有这个mutex时候,就相当于openmutex
        HANDLE hHandle = CreateMutex(NULL, FALSE, "mutex_test");
        if (GetLastError() == ERROR_ALREADY_EXISTS)
        {
            cout << "you had run this program!" << endl;
            cout << "input c to close this window" << endl;
            PrintInfo(hHandle, 'c');
            return 1;
        }
        cout << "program run!" << endl;
        cout << "input s to exit program" <<endl;
       
        PrintInfo(hHandle, 's');
        return 1;
    }


    哲学家吃饭问题:

    const int PHILOSOPHERS = 5;          //哲学家人数
    const int TIME_EATING = 50;         //吃饭需要的时间 毫秒
    HANDLE event[PHILOSOPHERS];    //主线程同工作线程保持同步的句柄数组
    HANDLE mutex[PHILOSOPHERS];   //mutex数组,这里相当于公共资源筷子
    CRITICAL_SECTION cs;                //控制打印的临界区变量

    UINT WINAPI ThreadFunc(void* arg)
    {
        int num = (int)arg;
       
        DWORD ret = 0;
        while (1)
        {
            ret = WaitForMultipleObjects(2, mutex, TRUE, 1000);
            if (ret == WAIT_TIMEOUT)
            {
                Sleep(100);
                continue;
            }
            EnterCriticalSection(&cs);
                cout << "philosopher " << num << " eatting" << endl;
            LeaveCriticalSection(&cs);
            Sleep(TIME_EATING);
            break;
        }
        //设置时间为有信号
        SetEvent(event[num]);
        return 1;
    }
    int main(int argc, char* argv[])
    {
        HANDLE hThread;
        InitializeCriticalSection(&cs);
        //循环建立线程
        for (int i = 0; i < PHILOSOPHERS; i++)
        {
            mutex[i] = CreateMutex(NULL, FALSE, "");
            event[i] = CreateEvent(NULL, TRUE, FALSE, "");
            hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunc, (void*)i, 0, NULL);
            if (hThread == 0)
            {
                cout << "create thread " << i << "failed with code: "
                    << GetLastError() << endl;
                DeleteCriticalSection(&cs);
                return -1;
            }
            CloseHandle(hThread);
        }
       
        //等待所有的哲学家吃饭结束
        DWORD ret = WaitForMultipleObjects(PHILOSOPHERS, event, TRUE, INFINITE);
        if (ret == WAIT_OBJECT_0)
        {
            cout << "all the philosophers had a dinner!" << endl;
        }
        else
        {
            cout << "WaitForMultipleObjects failed with code: " << GetLastError() << endl;
        }
        DeleteCriticalSection(&cs);
        for (int j = 0; j < PHILOSOPHERS; j++)
        {
            CloseHandle(mutex[j]);
        }
        return 1;
    }

     

    三 事件
    事件对象的特点是它可以应用在重叠I/O(overlapped I/0)上,比如说socket编程中有两种模型,一种是
    重叠I/0,一种是完成端口都是可以使用事件同步。它也是核心对象,因此可以被waitforsingleobje这些函数等待;事件可以有名字,因此可以被其他进程开启。我在前几个例子当中其实已经使用到event了,在这里就不多说了,可以参考前一个例子。

     

    四 信号量
    semaphore的概念理解起来可能要比mutex还难, 我先简单说一下创建信号量的函数,因为我在开始使
    用的时候没有很快弄清楚,可能现在还有理解不对的地方,如果有错误还是请大侠多多指教。
    CreateSemaphore(
      LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,  // SD
      LONG lInitialCount,                                               // initial count
      LONG lMaximumCount,                                            // maximum count
      LPCTSTR lpName                                                   // object name
    )
    第一个参数是安全性,可以使用默认的安全性选项NULL;第二个和第三个参数是两个long型的数值,
    它们表示什么含义呢?lMaxinumCount表示信号量的最大值,必须要大于零。比如是5就表示可以有5个进程或者线程使用,如果第六个进程或者线程想使用的话就必须进入等待队列等待有进程或者线程释放资源。lInitalCount表示信号量的初始值,应该大于或者等于零小于等于lMaximumCount。如果lInitialCount = 0 && lMaximumCount == 5,那么就表示当前资源已经全部被使用,如果再有进程或者线程想使用的话,信号量就会变成-1,该进程或者线程进入等待队列,直到有进程或者线程执行ReleaseMutex;如果lInitialCount = 5 && lMaximumCount == 5,那么就表示现在信号量可以被进程或者线程使用5次,再之后就要进行等待;如果InitialCount = 2 && MaximumCount == 5这样的用法不太常见,表示还可以调用两次CreateSemaphore或者OpenSemaphore,再调用的话就要进入等待状态。最后一个参数表示这个信号量的名字,这样就可以跨进程的时候通过这个名字OpenSemaphore。说了这么多了,不知道说明白没有~


    看个例子,popo现在好像在本机只能运行三个实例,我们在前面说的mutex可以让程序只是运行一个实
    例,下面我通过信号量机制让程序像popo一样运行三个实例。

    #include "stdafx.h"
    #include <windows.h>
    #include <iostream>
    using namespace std;

    const int MAX_RUNNUM = 3;  //最多运行实例个数
    void PrintInfo()
    {
        char c;
        cout << "run program" << endl;
        cout << "input s to exit program!" << endl;
        while (1)
        {
            cin >> c;
            if (c == 's')
            {
                break;
            }
            Sleep(10);
        }
    }
    int main(int argc, char* argv[])
    {
       
        HANDLE hSe = CreateSemaphore(NULL, MAX_RUNNUM, MAX_RUNNUM, "semaphore_test");
        DWORD ret = 0;
       
        if (hSe == NULL)
        {
            cout << "createsemaphore failed with code: " << GetLastError() << endl;
            return -1;
        }
      
       
        ret = WaitForSingleObject(hSe, 1000);
        if (ret == WAIT_TIMEOUT)
        {
            cout << "you have runned " << MAX_RUNNUM << " program!" << endl;
            ret = WaitForSingleObject(hSe, INFINITE); 
        }
       
        PrintInfo();
        ReleaseSemaphore(hSe, 1, NULL);
        CloseHandle(hSe);
     return 0;
    }

     

    附录:
    核心对象
    Change notification
    Console input
    Event
    Job
    Mutex
    Process
    Semaphore
    Thread
    Waitable timer

    展开全文
  • 线程的同步

    2011-11-08 20:29:51
    实例,生产者和消费者。 分析: 生产者-消费者问题是多线程同步处理的典型问题 一块生产者和消费者共享的界缓冲区,...一种是采用某种机制保持生产者和消费者之间的同步(较高的效率并且可控制性较好,比较常用
  • 所谓的同步就是线程之间进行数据一致性需要用到的机制。 一、互斥锁mutex(pthread_mutex_t) pthread_mutex_t,读写都独占的模式。最常用的模式,也就是编码中最喜欢用的。。。。 1.1、一旦一个线程拿到锁,另一...
  • windows线程同步

    2015-07-27 20:16:00
    一、前言 ... windows线程同步机制常用的有几种:Event、Critical Section、Mutex、Semaphore。 1.Critical Section(临界区) 适用范围: 单一进程的各线程之间用来排它性占有 特性: 不是内核...
  • 理解线程同步

    2015-02-27 17:34:48
    线程同步是指多线程通过特定的东西(如互斥...线程同步有三种常用的机制: 互斥量(mutex), 读写锁(rwlock)和条件变量(cond). 互斥量  互斥量从本质上说就是一把锁, 提供对共享资源的保护访问. 1. 初始化:  在Linux
  •   【转】... 最近由于使用多线程,不可避免的要用到线程之间的同步,对一些常用的windows 中同步函数和机制有了一些初步的了解,并且写了一些小例子来验证,当然其中难免有错误和疏漏之处,希望高手
  • 多线程模型

    千次阅读 2018-02-07 16:45:06
    就是由一个线程生产任务,而另外一个线程执行任务,二个线程之间有一个共享数据区,这种数据结构可以用队列来表示,但是必须是并发同步的,也就是就共享数据队列同一时间只能允许一个线程进行访问。这种机制叫做同步...
  • 并发与多线程

    2019-11-17 14:04:37
    重点知识线程的状态转换、线程的同步与互斥、线程池的运作机制详解,以及 JUC 中常用的工具类。 多线程知识点 多线程协作时,因为对资源的锁定与等待会产生死锁,这里需要了解产生死锁的四个基本条件,要明白竞争...
  • Java内存模型与多线程

    2018-01-29 22:45:03
    继 Java虚拟机基础知识汇总 (二),在此基础上,进一步介绍Java的内存模型及其和并发编程的关系。 在并发编程中,非常重要的两个问题是: 线程间如何通信,通信是...线程之间同步常用的方式:使用Synchromized关键
  • 生产者消费者问题是研究多线程程序时绕不开经典问题之一,它描述是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题方法可分为两类:(1)采用某种机制...
  • WIN32上的多线程

    2008-09-27 18:17:00
    最近由于使用多线程,不可避免的要用到线程之间的同步,对一些常用的windows 中同步函数和机制有了一些初步的了解,并且写了一些小例子来验证,当然其中难免有错误和疏漏之处,希望高手能给我这个小鸟指出不足之处,...
  • Java 多线程之生产者消费者一、简介在多线程学习中经常会遇到一个经典问题便是生产者消费者模式,它描述了一款作为仓库缓冲区,生产者将产品放入产库,消费者从仓库将产品拿走一个过程。解决生产者/消费者...
  • 解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步;(2)在生产者和消费者之间建立一个管道。第一种方式较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。...
  • 生产者消费者问题是研究多线程程序时绕不开经典问题之一,它描述是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题方法可分为两类:(1)采用某种机制...
  •  解决生产者消费者问题的方法两种,一种是采用某种机制保持生产者和消费者之间的同步,一种是在生产者和消费者之间建立一个管道。前一种较高的效率并且可控制性较好,比较常用,后一种由于管道缓冲区不易...
  • 线程面试:生产者 消费者问题

    千次阅读 2017-07-07 15:04:00
    生产者消费者问题是研究多线程程序时绕不开经典问题之一,它描述是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题方法可分为两类:(1)采用某种机制...
  • 2)用线程实现经典生产者消费者...Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。 生产者与消费者模型中,要保证以下几点: 同一时间内只能一个生产者生产 生产方法加锁sychronized 同一时间
  • 线程通信和线程池

    2019-08-14 21:49:38
    它描述的是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者可以从仓库中取走产品,解决生产者/消费者问题,我们需要采用某种机制保护生产者和消费者之间的同步 同步问题核心在于:如何保证同一资源被个...
  • Pthread锁机制

    2017-03-06 11:30:25
    线程同步(ThreadSynchronization)是并行编程中非常重要通讯手段,其中最典型应用就是用Pthreads提供机制(lock)来对线程之间共享临界区(CriticalSection)进行保护 Pthreads提供了多种锁机制,常见的有:...
  • 生产者消费者问题是研究多线程程序时绕不开经典问题之一,它描述是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题方法可分为两类:(1)采用某种机制...
  • assertion(断言)在软件开发中是一种常用的调试方式,很开发语言中都支持这种机制。在实现中,assertion就是在程序中的一条语句,它对一个boolean表达式进行检查,一个正确程序必须保证这个boolean表达式的值为...
  • 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。...常用的同步方法是采用信号或加锁机制,保证资源在任意

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 166
精华内容 66
关键字:

多线程之间常用的同步机制有