精华内容
下载资源
问答
  • Linux线程条件变量互斥锁

    1. Linux线程条件变量

      条件变量是另一种逻辑比较复杂一点的线程同步互斥机制,它必须与互斥锁一起配合使用,它的应用场景也是很常见的,先来看一个例子
      小明、小华和小刚公用一张银行卡,每个人都可以从这张卡上取钱。银行卡余额很显然是一个由很多人共同操作的典型的共享资源,因此,任何人使用之前都需要加锁,在余额为0的情况下,需要进入某个条件变量等待队列中等待,在父母向这张卡上打钱之后,通知他们三个银行卡上有钱了,它们可以根据银行卡上的余额与自己的需求金额,进行取钱或者继续等待

    2. Linux线程条件变量函数接口

    初始化条件变量的函数原型:

    int pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *a);

    cv 参数:条件变量

    a 参数:条件变量的属性,一般设置为NULL

    与其它同步互斥机制一样,条件变量在开始使用之前必须初始化,初始化函数中的属性一般设置为NULL即可。

    销毁条件变量的函数原型:

    int pthread_cond_destroy(pthread_cond_t *cv);

    cv 参数:条件变量

    当使用pthread_cond_destroy()销毁一个条件变量之后,它的值变得不确定,在使用时必须重新初始化

    进入条件变量等待队列的函数原型:

    int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *mutex);

    int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mutex, const struct timespec *t);

    cv 参数:条件变量

    mutex 参数:互斥锁

    t 参数:超时时间限制

    以上两个函数的功能是一样的,区别是pthread_cond_timedwait()函数可以设置超时时间

    唤醒条件变量等待的函数原型:

    int pthread_cond_broadcast (pthread_cond_t *cv);

    int pthread_cond_signal (pthread_cond_t *cv);

    cv 参数:条件变量

    a. 以上两个函数用来唤醒阻塞在条件变量等待队列中的线程,顾名思义,pthread_cond_broadcast用来唤醒全部线程,pthread_cond_signal只唤醒一个等待队列中的线程
    b. 注意,被唤醒的线程并不能立即从pthread_cond_wait()中返回,而是必须先获得配套的互斥锁

    3. Linux线程条件变量示例代码

    以下代码展示了小明、小华和小刚三个人如何取钱

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <pthread.h>
    #include <semaphore.h>
    
    int balancce = 0;       //共享资源:银行卡余额
    pthread_mutex_t m;      //互斥锁
    pthread_cond_t cond;    //条件变量
    
    void *routine(void *args){
        //加锁,取钱
        pthread_mutex_lock(&m);
        
        //如果余额不足,则进入条件等待队列
        while(balancce < 100){
            pthread_cond_wait(&cond, &m);
        }
        
        //如果余额充足,则进行取钱动作
        fprintf(stderr, "t%d: balance = %d\n", *(int *)args, balancce);
        balancce -= 100;
       
        //取完钱进行解锁动作
        pthread_mutex_unlock(&m);
        
        //退出线程
        pthread_exit(NULL);
    }
    
    int main(int argc, char**argv){
    
        //入参检查,比如传入要创建的线程数目
        if(argc < 2){
            printf("Usage: %s <thread_num> \n", argv[0]);
            return 1;
        }
    
        //互斥锁和条件变量进行初始化
        pthread_mutex_init(&m, NULL);
        pthread_cond_init(&cond, NULL);
    
        //循环创建若干条线程,这些线程执行取钱的动作
        pthread_t tid;
        int i;
        int thread_num = atoi(argv[1]);
        for(i = 0; i < thread_num; i++){
            pthread_create(&tid, NULL, routine, &i);
        }
    
        //接下来要往银行卡里打钱
        pthread_mutex_lock(&m);         //先加锁
        balancce += 100*thread_num;     //根据线程数打钱
        pthread_cond_broadcast(&cond);  //通知在条件变量等待队列中的线程
        pthread_mutex_unlock(&m);       //解锁
        
        //主线程退出
        pthread_exit(NULL);
    }
    

    在这里插入图片描述

    展开全文
  • linux 条件变量互斥锁

    千次阅读 2012-06-07 17:34:08
    条件变量,与不同, 条件变量用于等待某个条件被触发 基本编写的代码如下: // 线程一代码 ================================================= pthread_mutex_lock(&mutex); // 设置条件为true .....
    条件变量,与锁不同, 条件变量用于等待某个条件被触发
    


    基本编写的代码如下:



    // 线程一代码 =================================================
    pthread_mutex_lock(&mutex);
    // 设置条件为true


    ... 操作


    pthread_cond_signal(&cond);  // 条件满足时通过线程二
    pthread_mutex_unlock(&mutex);


    // 线程二代码 =================================================
    pthread_mutex_lock(&mutex);
    while (条件为false)
        pthread_cond_wait(&cond, &mutex); // 永久或超时等待线程一通知条件满足
    修改该条件


    ... 操作


    pthread_mutex_unlock(&mutex);



    需要注意几点:

    1) 第二段代码之所以在pthread_cond_wait外面包含一个while循环不停测试条件是否成立的原因是, 在pthread_cond_wait被唤醒的时候可能该条件已经不成立.


    UNPV2对这个的描述是:

    "Notice that when pthread_cond_wait returns, we always test the condition again, because spurious wakeups can occur: a wakeup when the desired condition is still not true.".



    2) pthread_cond_wait调用必须和某一个mutex一起调用, 这个mutex是在外部进行加锁的mutex, 在调用pthread_cond_wait时, 内部的实现将首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁.


    man文档中对这部分的说明是:

    pthread_cond_wait atomically unlocks the mutex (as per pthread_unlock_mutex) and waits for the condition variable cond to  be  signaled.  The thread execution is suspended and does not consume any CPU time until the condition variable is

    signaled. The mutex must be locked by the calling thread on entrance to pthread_cond_wait.  Before  returning  to  the calling thread, pthread_cond_wait re-acquires mutex (as per pthread_lock_mutex).


    也就是说pthread_cond_wait实际上可以看作是以下几个动作的合体:
    解锁线程锁
    等待条件为true
    加锁线程锁.


    请看具体的pthread_cond_wait代码实现:

    /* 基于条件变量阻塞 / 在指定的时间之前阻塞 */
    bool32 ktx_condv_wait(McCondv *_cv, McMutex*mtx, si32 millis) {
    	bool32 waitForever;
    	struct timeval tv;
    	struct timespec timeout;
    	int status = 0;
    	CVMCondVar *cv = (CVMCondVar*) _cv;
    	CVMThreadID * self = ktx_thread_cur_get();
    
    	CCEAssert(self != NULL);
    	CCEAssert(cv != NULL);
    	CCEAssert(mtx != NULL);
    
    	waitForever = (millis < 0) ? TRUE : FALSE;
    
    	if (waitForever == FALSE) {
    		gettimeofday(&tv, NULL);
    
    		timeout.tv_sec = tv.tv_sec + (millis / 1000LL);
    		timeout.tv_nsec = tv.tv_usec * 1000;
    		timeout.tv_nsec += (millis % 1000) * 1000000;
    
    		if (timeout.tv_nsec >= 1000000000) {
    			++timeout.tv_sec;
    			timeout.tv_nsec -= 1000000000;
    		}
    	}
    
    	/**************************************************/
    	ktx_mutex_lock((McMutex*) &(self->lock));
    	if (self->interrupted) {
    		self->interrupted = FALSE;
    		ktx_mutex_unlock((McMutex*) &self->lock);
    		return FALSE;
    	}
    
    	self->notified = FALSE;
    	self->isWaitBlocked = TRUE;
    
    	/* add ourself to the wait queue that notify and notifyAll look at */
    	CVMcondvarEnqueue(cv, self);
    
    	ktx_mutex_unlock((McMutex*) &self->lock);
    	/**************************************************/
    	ktx_mutex_unlock(mtx);  这里解锁线程锁,下面立即进行等待条件为true
    
    	/* notifies can happen now */
    	pthread_mutex_lock(&self->wait_mutex);
    	while (self->value == 0) {
    		if (waitForever) {
    			pthread_cond_wait(&self->wait_cv, &self->wait_mutex);
    		} else {
    			status = pthread_cond_timedwait(&self->wait_cv, &self->wait_mutex,
    					&timeout);
    			if (status == ETIMEDOUT) {
    				break;
    			}
    		}
    	}
    
    	pthread_mutex_unlock(&self->wait_mutex);
    	
    	/* 获得lock之后才可以处理挂起操作:加锁线程锁 */
    	ktx_mutex_lock((McMutex*) &self->lock);
    
    	/* If we're supposed to be suspended, then suspend self: */
    	//while (self->isSuspended) 
    	//{
    	//	suspendSelf();
    	//}
    
    	self->isWaitBlocked = FALSE;
    	ktx_mutex_unlock((McMutex*) &(self->lock));
    	/* ---------------------------------------- */
    
    	/* reacquire condvar mutex */
    	ktx_mutex_lock(mtx);
    
    	/* find out why we were woken up */
    	if (self->notified) {
    		/* normal notify or notifyAll */
    		CCEAssert(self->value == 1);
    		/* removed from wait queue */
    		CCEAssert(self->next == NULL && self->prev_p == NULL);
    	} else {
    		/*
    		 * We were woken up by linuxSyncInterruptWait() posting on
    		 * the semaphore, or the timed wait timed out.
    		 */
    		CCEAssert(self->interrupted || !waitForever);
    		CVMcondvarDequeueSelf(cv, self);
    
    		/* removed from wait queue */
    		CCEAssert(self->next == NULL && self->prev_p == NULL);
    	}
    
    	self->value = 0;
    
    	if (self->interrupted) {
    		self->interrupted = FALSE;
    		return FALSE;
    	}
    
    	/* 等待超时返回失败 */
    	if (waitForever == FALSE && status == ETIMEDOUT)
    		return FALSE;
    
    	return TRUE;
    }


    展开全文
  • Linux互斥锁条件变量和信号量 Linux互斥锁条件变量和信号量 Linux互斥锁条件变量和信号量 Linux互斥锁条件变量和信号量 Linux互斥锁条件变量和信号量 Linux互斥锁条件变量和信号量 Linux互斥锁条件...
  • linux进程间互斥锁条件变量

    千次阅读 2020-02-18 20:58:46
    设置进程间共享属性互斥锁条件变量 将该互斥锁条件变量放到共享内存中 public.h #ifndef _PUBLIC_H #define _PUBLIC_H #include <pthread.h> #include <string.h> #include <stdio.h> #...

    1. 设置进程间共享属性互斥锁和条件变量
    2. 将该互斥锁和条件变量放到共享内存中

    public.h

    #ifndef _PUBLIC_H
    #define _PUBLIC_H
    
    #include <pthread.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <ctype.h>
    #include <sys/mman.h>
    #include <sys/stat.h>        /* For mode constants */
    #include <fcntl.h>           /* For O_* constants */
    
    typedef struct interaction {
    	int id;
    	char name[8];
        pthread_cond_t cond;
        pthread_mutex_t mutex;
    }Interaction;
    
    extern Interaction* get_interaction(const char *filename);
    
    #endif // _PUBLIC_H
    

    interaction.c

    #include "public.h"
    
    Interaction* get_interaction(const char *filename)
    {
        Interaction *share_mem;
    	int len = sizeof(Interaction);
    
        int fd = shm_open(filename, O_RDWR|O_CREAT|O_EXCL, 0777);
        if (fd > 0) {
            /**< 设置共享内存长度 */
            ftruncate(fd, len);
            share_mem = (Interaction *)mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
            pthread_condattr_t cond_attr;
            pthread_condattr_init(&cond_attr);
            pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);
            pthread_cond_init(&share_mem->cond, &cond_attr);
    
    
            pthread_mutexattr_t mutex_attr;
            pthread_mutexattr_init(&mutex_attr);
            pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED);
            pthread_mutex_init(&share_mem->mutex, &mutex_attr);
    
    		printf("mmap Interaction object(%p) ok\n", share_mem);
        } else {
    		perror("ready");
            fd = shm_open(filename, O_RDWR, 0777);
            /**< 其他进程已经初始化过了,这里不要再初始化 */
            share_mem = (Interaction *)mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    		printf("get Interaction object(%p) ok\n", share_mem);
        }
        close(fd);
    //    shm_unlink("/test_share_mem"); 
    
        return share_mem;
    }
    

    signal.c

    #include "public.h"
    
    int main()
    {
    	Interaction *share_mem = get_interaction("test_share_mem");
        
        while (1) {
            char buf[1024];
            fgets(buf, sizeof(buf), stdin);
    		strncpy(share_mem->name, buf, 7);
    		printf("send condtion signal\n");
            pthread_cond_signal(&share_mem->cond);
        }
    }
    

    wait.c

    #include "public.h"
    
    int main()
    {
    	Interaction *share_mem = get_interaction("test_share_mem");
    	pthread_cond_t *cond = &share_mem->cond;
    	pthread_mutex_t *mutex = &share_mem->mutex;
    
        while (1) {
            pthread_mutex_lock(mutex);  
            pthread_cond_wait(cond, mutex);  
            pthread_mutex_unlock(mutex);
    
            printf("get Interaction: %s\n", share_mem->name);
        }
    }
    
    展开全文
  • Linux互斥锁条件变量

    千次阅读 2016-07-29 15:30:25
    #include ... //互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能 //得到这个互斥锁 pthread_mutexattr_
    #include <pthread.h>
    
    class thread_lock
    {
    public:
    	thread_lock()
    	{
    		pthread_mutexattr_init(&m_mutexatr);
    //互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能//得到这个互斥锁
    		pthread_mutexattr_settype(&m_mutexatr, PTHREAD_MUTEX_RECURSIVE);
    		pthread_mutex_init(&m_mutex, &m_mutexatr);
    		pthread_cond_init(&m_cond, NULL);
    	}
    
    	~thread_lock()
    	{
    		pthread_mutexattr_destroy(&m_mutexatr);
    		pthread_mutex_destroy(&m_mutex);
    		pthread_cond_destroy(&m_cond);
    	}
    	
    	void lock()
    	{
    		pthread_mutex_lock(&m_mutex);
    	}
    
    	void unlock()
    	{
    		pthread_mutex_unlock(&m_mutex);
    	}
    
    	void wait()
    	{
    		pthread_cond_wait(&m_cond, &m_mutex);
    	}
    
    	void signal()
    	{
    		pthread_cond_signal(&m_cond);
    	}
    
    private:
    	pthread_mutex_t m_mutex;
    	pthread_mutexattr_t m_mutexatr;
    	pthread_cond_t m_cond;
    };
    
    #endif
    void read()
    {
    	while (true)
    	{
    		m_thread_lock.lock();
    		if (m_list_task.empty())
    		{
    			m_thread_lock.wait();
    		}
    		task* ptask = m_list_task.front();
    		m_list_task.pop_front();
    		m_thread_lock.unlock();
    		ptask->run();
    		delete ptask;
    	}
    }
    
    void write(task* ptask)
    {
    	m_thread_lock.lock();
    	m_list_task.push_back(ptask);
    	m_thread_lock.signal();
    	m_thread_lock.unlock();
    }

    刚开始使用条件变量的时候,一直都在想如果在read函数中m_thread_lock.wait()阻塞住了等待新的数据,那么另外的写线程在write中没法m_thread_lock.lock(),那么就没法发送m_thread_lock.signal(),也就是没法触发read县城了,就会造成永远阻塞的结果了。读了多线程手册才发现,pthread_cond_wait的实际作用。

    线程调用pthread_cond_wait这个函数之后,内核会做下面这些事:
    1. 拿到锁的线程,把锁暂时释放;
    2. 线程休眠,进行等待;
    3. 线程等待通知,要醒来。(重新获取锁)
    线程库将上面三步做成了原子性操作,和Linux内核绑定在一起。

    展开全文
  • linux互斥锁条件变量的关系

    千次阅读 2017-02-26 02:18:44
    条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起配合使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。...
  • 互斥锁是一个二元变量,主要以排他的方式防止数据被并发访问。 1、初始化互斥锁 #include &amp;lt;pthread.h&amp;gt; /*动态初始化互斥锁*/ int pthread_mutex_init(pthread_mutex_t* mutex,pthread_...
  • Linux多线程 互斥锁条件变量使用

    千次阅读 2013-06-07 13:26:03
    linux下,锁的种类很多,包括互斥锁,文件锁,读写锁······其实信号量说白了也是一种锁。互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。 1. 初始化: 线程的互斥量数据类型是pthread_mutex_t,...
  • 与进程类似,线程也存在...通常来说用户可以使用互斥量(互斥锁)或者的条件变量条件锁)的方式来解决线程的同步问题。 互斥锁  互斥锁是一个简单的锁定命令,它可以用来锁定共享资源使得其他线程无法访问。互...
  • 条件变量与互斥量互斥量条件变量为什么有互斥锁,还需要条件变量? 互斥量 互斥量(mutex)从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁以后,任何其他...
  • linux下的互斥锁条件变量和信号量

    千次阅读 2012-04-01 23:27:41
    Linux下,提供了互斥锁条件变量和信号量来对共享资源进行保护。 一、互斥锁 互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。 需要的头文件:pthread.h 互斥锁
  • 简单来说,互斥锁类似于一个布尔变量,它只有“锁定”和“打开”两种状态,在使用临界资源时线程先申请互斥锁,如果此时互斥锁处于“打开”状态,则立刻占有该锁,将状态置为“锁定”。此时如果再有其他线程使用该...
  • 转自http://www.docin.com/p-1216151083.html,本人为原作者才情所倾倒,转载仅为学习所用,若有冒犯,立即删除。 正文    
  • Linux线程中的互斥锁条件变量 1. 互斥锁 互斥锁用于保护临界区资源(实际保护的是临界区中被操纵的数据),通常用于保护多个线程间的共享数据。而这些共享数据通常是一些可供线程间使用的全局变量/硬件寄存器等,为...
  • 以下内容来源自UNP卷二的第八章 读写的概念( the conception of read-write lock ) (1)只要没有线程持有某个给定的读写用于写,那么任意...因为获取一个读写用于读是共享,获取一个读写用于写是独占。 ...
  • 首先我的理解什么是互斥锁,什么是条件变量,他们的作用是什么? 互斥锁:可以理解为它本身是一把锁,用于对资源进行保护。 条件变量:是利用线程间共享的全局变量进行同步的一中机制。主要包括两个动作:一个线程...
  • Linux--Linux互斥锁条件变量和信号量 2010-01-04 16:04 进行多线程编程,最应该注意的就是那些共享的数据,因为无法知道哪个线程会在哪个时候对它进行操作,也无法得知哪个线程会先运行,哪个线程会后运行。所以...
  • Linux下,提供了互斥锁条件变量和信号量来对共享资源进行保护。 一、互斥锁 互斥锁,是一种信号量,常用来防止两个进程或线程在同一时刻访问相同的共享资源。 需要的头文件:pthread.h 互斥锁
  • 封装linux 条件互斥锁

    千次阅读 2015-07-27 23:38:30
    linux互斥锁条件变量的简单封装
  • 前言在学习posix ipc编程的时候,遇到两个很重要的概念:互斥锁条件变量,而且,在各种进程/线程之间的同步中的使用很多。所以今天就系统的整理了一下,主要的参考资料来自《UNIX网络编程 卷2:进程间通信》一、...
  • 条件变量必须始终与互斥锁配合,以避免竞争状态:其中线程准备等待一个条件,另一个线程刚好在第一个线程 真正等待 之前发出条件信号。 网友: pthread_cond_wait总和一个互斥锁结合使用。在调用pthread_cond_wait...
  • 一、互斥锁 互斥量从本质上说就是一把锁, 提供对共享资源的保护访问。 1. 初始化: 在Linux下, 线程的互斥量数据类型是pthread_mutex_t. 在使用前, 要对它进行初始化: 对于静态分配的互斥量, 可以把它设置为...
  • pthread_cond_wait与pthread_cond_signal为什么需要锁变量保护

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,981
精华内容 14,392
关键字:

linux条件变量互斥锁

linux 订阅