【Linux】Mutex互斥量线程同步的例子

0、互斥量

 Windows下的互斥量

是个内核对象,每次WaitForSingleObject和ReleaseMutex时都会检查当前线程ID和占有互斥量的线程ID是否一致。

当多次Wait**时就要对应多次ReleaseMutex, 当ReleaseMutex过多次数时如果发现当前占有互斥量的线程ID和当前调用ReleaseMutex的线程ID不一致时仅仅返回FLASE,GetLastError返回ERROR_NOT_OWNER,没有其他副作用。

当占有mutex的线程在Release之前退出时,该mutex被【遗弃】,此时系统自动收回mutex,可供其他线程申请。

允许多次等待

WaitForSingleObject(hMutex, time);

WaitForSingleObject(hMutex, itme);

多次等待 对应多次释放

ReleaseMutex(hMutex);

ReleaseMutex(hMutex);

Linux下的互斥量

可以设置互斥量的属性是否为可以被同一个线程多次lock,  还可以设置该互斥量的范围,即是用于进程之间同步 还是 同一进程不同线程之间的同步。

相关API 将说明见代码注释部分。

1、相关API

//Initialize a mutex with attribute(can be NULL)
int pthread_mutex_init(
     pthread_mutex_t* mutex,
     const pthread_mutexattr_t* mutexattr);                                                                           

//lock a mutex
int pthread_mutex_lock(pthread_mutex_t* mutex);                                                                       

//ulock a mutex
int pthread_mutex_unlock(pthread_mutex_t* mutex);                                                                     

//destroy a mutex
int pthread_mutex_destroy(pthread_mutex_t* mutex);                                                                    

int pthread_mutexattr_setpshared(
      pthread_mutexattr_t* mattr,
      int pshared  //PTHREAD_PROCESS_SHARE | PTHREAD_PROCESS_PRIVATE
      );                                                                                                              

int pthread_mutexattr_getshared(
pthread_mutexattr_t* mattr,
int* pshared);                                                                                                        

int pthread_mutexattr_settype(
     pthread_mutexattr_t* attr,
     int type  //PTHREAD_MUTEX_TIMED_NP -- default value
               //PTHREAD_MUTEX_RECURISIVE_NP -- allow a thread lock multitimes
               //PTHREAD_MUTEX_ERRORCHECK_NO -- check error lock, return EDEADLK if the same thread want to LOCK
               //PTHREAD_MUTEX_ADAPTIVE_NO -- adaptive lock, the simplest lock
)                                                                                                                     

int pthread_mutexattr_gettype(
     pthread_mutexattr_t* attr,
     int* type
)                                                                                                                     

2、demo

#include <iostream>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>

using namespace std;

/***********************************************
 *
 * Initialize a mutex with attribute(can be NULL)
 * int pthread_mutex_init(
 *      pthread_mutex_t* mutex,
 *      const pthread_mutexattr_t* mutexattr);
 *
 * lock a mutex
 * int pthread_mutex_lock(pthread_mutex_t* mutex);
 *
 * unlock a mutex
 * int pthread_mutex_unlock(pthread_mutex_t* mutex);
 *
 * destroy a mutex
 * int pthread_mutex_destroy(pthread_mutex_t* mutex);
 *
 * int pthread_mutexattr_setpshared(
 *       pthread_mutexattr_t* mattr,
 *       int pshared  //PTHREAD_PROCESS_SHARE | PTHREAD_PROCESS_PRIVATE
 *       );
 *
 * int pthread_mutexattr_getshared(
 * pthread_mutexattr_t* mattr,
 * int* pshared);
 *
 * int pthread_mutexattr_settype(
 *         pthread_mutexattr_t* attr,
 *         int type  //PTHREAD_MUTEX_TIMED_NP -- default value
 *                   //PTHREAD_MUTEX_RECURISIVE_NP -- allow a thread lock multitimes
 *                   //PTHREAD_MUTEX_ERRORCHECK_NO -- check error lock, return EDEADLK if the same thread want to LOCK
 *                   //PTHREAD_MUTEX_ADAPTIVE_NO -- adaptive lock, the simplest lock
 * )
 *
 *
 * int pthread_mutexattr_gettype(
 *         pthread_mutexattr_t* attr,
 *         int* type
 * )
 * *********************************************/

void* work_thread(void* p)
{
    if (NULL == p)
        return  const_cast<char*>("invalid thread argument");

    pthread_mutex_t* pMutex = (pthread_mutex_t*)(p);

    //current thread ID
    pthread_t nThreadID = pthread_self();

    int i = 0;
    while(++ i <= 3)
    {
        //lock multi times
        pthread_mutex_lock(pMutex);
        pthread_mutex_lock(pMutex);

        cout << "Thread " << nThreadID << " is Running! " << endl;    

        //and so unlock multi times
        pthread_mutex_unlock(pMutex);
        pthread_mutex_unlock(pMutex);
        usleep(1000 * 1); //1 miliseconds
    }

    return const_cast<char*>("------ finish -----------");

}

void* work_thread2(void* p)
{
    if (NULL == p)
        return  const_cast<char*>("invalid thread argument");

    pthread_mutex_t* pMutex = (pthread_mutex_t*)(p);

    //current thread ID
    pthread_t nThreadID = pthread_self();

    int i = 0;
    while(++ i <= 3)
    {
        //if current thread can not enter mutex,
        //and the function pthread_mutex_trylock will RETURN Immediatly
        if ( EBUSY == pthread_mutex_trylock(pMutex))
            cout << "Other thread is lock the resouce, i am waiting.." << endl;
        else
        {
            cout << "Thread " << nThreadID << " is Running! " << endl;
            pthread_mutex_unlock(pMutex);
            usleep(1000 * 1); //1 miliseconds
        }

    }
    return const_cast<char*>("------ finish -----------");

}

int main()
{
    const size_t nThreadCount = 3;
    pthread_t threadIDs[nThreadCount];
    int nRet = -1;
    pthread_mutex_t mutex;
    pthread_mutexattr_t mutexattr;
    void* pRet = NULL; //thread return value

    //allow a thread lock multi times
    nRet = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);

    nRet = pthread_mutex_init(&mutex, &mutexattr);
    if (0 != nRet)
        return -1;

    for (size_t i = 0; i < nThreadCount - 1; ++ i)
    {
        nRet = pthread_create(&threadIDs[i], NULL, work_thread, (void*)(&mutex));
        if (0 != nRet)
            continue;
    }    

    nRet = pthread_create(&threadIDs[nThreadCount - 1], NULL, work_thread2, (void*)(&mutex));
    if (0 != nRet)
        cerr << endl << "work_thread2 created falied! " << endl;

    for (size_t i = 0; i < nThreadCount; ++ i)
    {
        nRet = pthread_join(threadIDs[i], &pRet);
        if (0 == nRet)
        {
            cout << " Thread " << threadIDs[i] << " Finished ! "                 " It‘s return value is " << (char*)pRet << endl;
        }

    }

    pthread_mutex_destroy(&mutex);

    return 0;
}

3、执行结果

时间: 2024-10-14 23:40:52

【Linux】Mutex互斥量线程同步的例子的相关文章

一个简单例子了解使用互斥量线程同步

在刚开始学习学习线程同步时总是认为两个线程或是多个线程共同运行,但是那样是做的. 同步就是协同步调,按预定的先后次序进行运行.如:你说完,我再说. "同"字从字面上容易理解为一起动作. 其实不是,"同"字应是指协同.协助.互相配合. 如进程.线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行:B依言执行,再将结果给A:A再继续操作. 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其它

【Linux】Semaphore信号量线程同步的例子

0. 信号量 Linux下的信号量和windows下的信号量稍有不同. Windows Windows下的信号量有一个最大值和一个初始值,初始值和最大值可以不同.  而且Windows下的信号量是一个[内核对象],在整个OS都可以访问到. Linux Linux下的信号量在创建的时候可以指定一个初始值,这个初始值也是最大值. 而且Linux下的信号量可以根据需要设置为是否是[进程间共享]的,如果不是进程间共享的则就是一个本进程局部信号量.  1.相关API int semt_init( semt

VC++多线程同步(一) Mutex互斥量

一 .同步机制的引入目的是为了解决三个主要问题 1为了控制线程之间共享资源的同步访问,保证共享资源的完整性.(比如一个线程正在更新一个数据,而另外一个线程正在读取该数据,那么就不知道该数据是新的还是旧的,为了避免这种状况的发生) 2确保线程之间的动作,以制定的次序发送,例如一个线程的触发,需要另外一个线程的结果,作为条件. 3为了控制某一个共享资源的最大访问量,例如我们同时只能处理5个客户的请求,这时候,我们需要放到队列进行等待. 二.同步概念就是等待 WIN32  提供了API 等待函数 DW

VC++线程同步(二) Mutex互斥量的例子

同步对象使用实例 Win32窗口的建立: 我们将要学习的使用,分别是:互斥量,临界区,事件,信号量.所以我们需要一个窗口,呈现四种四种同步对象状态. 首先创建一个Win32项目,不要选空项目; 我们需要四个小窗口,先找到注册主窗口的代码. ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style= CS_HREDRAW | CS_VREDRAW

Linux系统开发9 线程同步

[本文谢绝转载原文来自http://990487026.blog.51cto.com] <大纲> Linux系统编程8 线程同步 多线程共享资源,不加锁,同步互斥演示 多线程共享资源,加锁,同步互斥演示 读写锁:3个写线程,5个读线程,不加锁,并行处理 读写锁:3个写线程,5个读线程,加读写锁,串行处理 条件变量:生产消费者模型 信号量 进程间锁 文件锁: 习题 死锁,哲学家就餐 多线程共享资源,不加锁,同步互斥演示 [email protected]:~/linux_c/thread$ ca

Linux下互斥量加锁与解锁操作的C代码实现

一.概述 在实际的软件程序中,由于代码量较大,函数之间的调用关系较为复杂,因此对于某些全局变量的操作要格外小心.在程序中,一般采用互斥量加锁的方式来保证对全局变量的操作的唯一性. 本文详细介绍了Linux下互斥量加锁与解锁操作的C代码实现,为相关的软件开发工作的开展提供了有益的参考. 二.加锁与解锁函数及时间结构体介绍 1.加锁函数pthread_mutex_timedlock 函数原型:int pthread_mutex_timedlock(pthread_mutex_t *restrict

学习pthreads,使用互斥量进行同步

在进行多线程编程时,我们总会遇到全局变量和数据结构的问题,这是多线程之间进行通信的问题.如果多个线程同时读写一个全局变量,那么会造成竞争或者出错.为了解决这一问题,我们需要对全局数据进行,使用互斥量实现锁的机制,当某个线程在某个操作前进行了加锁,那么某个操作只能在这个线程进行,直至将锁去除,相当于在这里将多线程的并行变成了串行.本文重点学习如何使用互斥量进行全局数据的同步,分为三个部分,第一部分给出代码示例,第二部分对代码进行讲解,第三部分给出运行结果. 一.代码示例 该程序使用4个线程实现两个

linux系统编程:线程同步-互斥量(mutex)

线程同步-互斥量(mutex) 线程同步 多个线程同时访问共享数据时可能会冲突,于是需要实现线程同步. 一个线程冲突的示例 #include <stdio.h> #include <unistd.h> #include <pthread.h> #define Loop 1000000 //全局资然 int counter = 0; void *fun(void *argv) { int i; for (i = 0; i < Loop; i++) { counter

c# Thread5——线程同步之基本原子操作。Mutex互斥量的使用

之前的博文也说到了如果多线程对于访问的公共资源操作都是原子操作,那么可以避免竞争条件.关于多线程的竞争可以百度. 1.执行最基本的原子操作 c#提供了一系列供我们使用的原子操作的方法和类型,比如我们的自增和自减操作. 看代码 class Program { private static int _count = 0; static void Main(string[] args) { var thread1 = new Thread(() => { for(int i = 0; i < 100