linux 线程同步(二)

信号量

信号量是互斥锁的升级版把互斥锁中1变成了n,举个简单的例子:假设现在有10个人,有一部手机,这10个人都竞争来使用手机打电话这就是互斥锁。对于信号量,现在可能是有4部手机,这10个人都竞争来使用手机打电话。相比互斥锁信号量由1变成了4。信号量相也就是操作系统中pv操作,它广泛应用进程或者线程间的同步与互斥。

相关库函数介绍

#include <semaphore.h>//所需头文件
//初始化信号量sem初始化的时候可以指定信号量的初始值,以及是否可以在多进程间共享value表示要信号量初始值,pshared表示是否再多进程之前共享。0表示不在多进程间
共享,非0表示在多进程之间共享具体可以man sem_init
//成功返回0,出错返回-1
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem)//相当于p操作
int sem_try_wait(sem_t *sem)//相当于p操作,在信号量值大于0时都能将信号量的值减一,与上面sem_wait的区别是,在信号值小于0时
int sem_post(sem_t *sem)//相当于v操作
int sem_getvalue(sem_t *sem)//用于得到信号量的值
int sem_destory(sem_t *sem) //释放信号量
 

信号量实例:生产者消费值

#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#define BUFSIZE  10
int buf[BUFSIZE];
sem_t consumer_sem,producer_sem;
void *consumer(void *arg)
{
	int c=0;
	while(1)
	{
		sem_wait(&consumer_sem);//开始消费consumer_sem值减一
		printf("consumer %d: %d\n",c,buf[c]);//消费数据
		c++;
		c=c%BUFSIZE;
	    sleep(1);//睡眠1s
		sem_post(&producer_sem);//producer_sem值加1
	}
}
void *producer(void *arg)
{
	int p=0;
	while(1)
	{
		sem_wait(&producer_sem);//开始生产producer_sem值减一
		buf[p]=rand() % 1000 + 1;//生产数据
		printf("producer %d: %d\n",p,buf[p]);
		p++;
		p=p%BUFSIZE;
		sem_post(&consumer_sem);//consumer_sem值加1

	}
}

int main()
{

	sem_init(&consumer_sem,0,0);
	sem_init(&producer_sem,0,BUFSIZE);

	pthread_t pid,cid;
	pthread_create(&pid,NULL,producer,NULL);
	pthread_create(&cid,NULL,consumer,NULL);

	pthread_join(pid, NULL);
	pthread_join(cid, NULL);
	sem_destroy(&consumer_sem);
	sem_destroy(&producer_sem);
	return 0;

}

条件变量

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

条件变量类型为 pthread_cond_t

相关库函数简介

#include<pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);//条件变量的资源释放
int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);//条件变量的初始化
 
#include<pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *mutex,
const struct timespec *abstime);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
//等待某个条件是否成立。对于timewait()函数除了等待以外,可以设置一个时长。
int pthread_cond_signal(pthread_cond_t *cond);//种情况是只有一个线程收到后执行动作。
//活动线程只需要唤醒第一个正在睡眠的线程。假设您只对队列添加了一个工作作业。那么只需要唤醒一个工作程序线程(再唤醒其它线程是不礼貌的!)
int pthread_cond_broadcast(pthread_cond_t *cond);//通过广播的形式发给子线程消息,子线程竞争执行。

无论哪种等待方式,都必须和互斥锁结合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait())的竞争条件,且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。

#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

struct msg {
    struct msg *next;
    int num;
};

struct msg *head;
/* 条件变量 */
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
void *consumer(void *p)
{
    struct msg *mp;
    while(1)
	{
        pthread_mutex_lock(&lock);
        /* pthread_cond_wait(&has_product, &lock);
         * 1.阻塞等待has_product被唤醒,
         * 2.释放互斥锁, pthread_mutex_unlock(&lock)
         * 3.当被唤醒时,解除阻塞,并且重新去申请获得互斥锁 pthread_mutex_lock(&lock)
         */
        while (head == NULL)
            pthread_cond_wait(&has_product, &lock);//等待

        mp = head;
        head = mp->next;
        pthread_mutex_unlock(&lock);
        printf("Consume %d\n", mp->num);
        free(mp);
        sleep(rand() % 5);
    }
}

void *producer(void *p)
{
    struct msg *mp;
    while(1)
	{
        mp =(struct msg *)malloc(sizeof(struct msg));
        mp->num = rand() % 1000 + 1;
        printf("Produce %d\n", mp->num);
        pthread_mutex_lock(&lock);
        mp->next = head;
        head = mp;
        pthread_mutex_unlock(&lock);
        /* pthread_cond_broadcast(&has_product) 唤醒等待队列上的所有线程*/
		//发送信号,告诉消费者有产品了
        pthread_cond_signal(&has_product);
        sleep(rand() % 5);
    }
}

int main(int argc, char *argv[])
{
    pthread_t pid, cid;
    srand(time(NULL));
    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);
    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    return 0;
}

版权声明:欢迎转载,如有不足之处,恳请斧正。

时间: 2024-10-29 11:40:31

linux 线程同步(二)的相关文章

使用信号量控制Linux线程同步

线程同步 在现实生活中,有些东西就必须是按顺序执行的,只有我完成了以后,你才能在我的劳动成果上接着干:不能我还没有完成,你就开始干活了.这就是线程同步最直白的解释了. 在进行程序设计时,亦是如此.线程同步,同步的是什么?它同步的是对共享资源(内存区域,公共变量等)或者临界区域的访问.有的时候,这些共享 资源和临界区域,就只能容忍一个线程对它进行操作(读或者写,读操作一般不控制,主要是写操作),这个时候,我们必须要对这些共享资源或者临界区域进行同 步,那么如何对它们进行线程同步呢? 在Linux中

【转】 Linux 线程同步的三种方法

线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量. 一.互斥锁(mutex) 通过锁机制实现线程间的同步. 初始化锁.在Linux下,线程的互斥量数据类型是pthread_mutex_t.在使用前,要对它进行初始化.静态分配:pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;动态分配:int pthread_mutex_init(pthread_m

linux线程同步(队列方式)

看了一些关于信号量的线程同步方式,今天用了一下. 我对于线程同步一直有疑问,在主线程和子线程处理时间不相同的时候,用这种信号量,如何保证同步. 假如主线程比较快,信号量连加了n个,但是子线程就不断减这个n,减到0.但是如果主线程太快太快,需要停一停,比如缓冲区快溢出了,主线程需要挂起. 由什么来唤醒主线程呢?子线程?不过这样的话,容易造成主线程死锁,或者主和子都卡死. 下面的程序,没有用到信号量同步,信号量只是负责开启子线程而已.主要是队列的实现而已.等我把上面的问题解决完会写上更新的程序. 队

linux线程(二)内存释放

linux线程有两种模式joinable和unjoinable. joinable线程:系统会保存线程资源(栈.ID.退出状态等)直到线程退出并且被其他线程join. unjoinable线程:系统会在线程退出时自动回收线程资源. linux线程创建后默认为joinable模式,因此线程退出时不会释放资源.若程序中大量的创建线程并未处理,则会导致内存泄漏,最终将导致不能继续创建线程. 应用举例: 1. 一般情况我们并不关注线程的状态,只是让其执行一些操作,所以要将线程设为unjoinable.实

Linux线程同步

线程同步-互斥锁 1.初始化互斥锁pthread_mutex_init() int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); 例: pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); 2.锁住互斥锁pthread_mutex_lock() int pthread_mutex_lock(pt

Linux线程同步---信号量

首先讲一下线程同步信号量的几个关键步骤! 1.定义并初始化信号量. (1) sem_t bin_sem; (2)  res = sem_init(&bin_sem,0,0); 详细步骤可以查看man帮助页面 2.使用信号量 (1) 信号量加1操作.sem_post(&bin_sem); (2) 信号量等待并减1操作.sem_wait(&bin_sem); 初始化后一般处于等待状态,执行某个操作后加1,而另个一个操作执行前进行等待操作.如果有多个线程,通常是一个线程进行加1操作,另外

LINUX线程同步初探

0x00.什么是线程同步 同步,又称直接制约关系,是指多个线程(或进程)为了合作完成任务,必须严格按照规定的 某种先后次序来运行 0x01.案例代码 1 void* PthreadFunc(void* argc); 2 int flag_num = 1; 3 4 int main(int argc, char* argv[]) 5 { 6 pthread_t pid; 7 void* ret_val; 8 9 int create_status = pthread_create(&pid, NU

Linux 线程同步的三种方法(互斥锁、条件变量、信号量)

互斥锁 1 #include <cstdio> 2 3 #include <cstdlib> 4 5 #include <unistd.h> 6 7 #include <pthread.h> 8 9 #include "iostream" 10 11 using namespace std; 12 13 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 14 15 int tmp; 16

Linux线程同步------屏障

屏障是Linux中协调多个线程并行工作的同步机制,屏障允许每个线程等待直到所有的合作线程到达某一点,然后继续从该点执行,pthread_join是一种屏障但只允许一个线程等待,pthread_barrier允许任意数量的线程等待! pthread_barrier_init(pthread_barrier_t *屏障,属性,unsigned int 屏障计数值): pthread_barrier_wait(pthread_barrier_t *屏障):在每个线程中调用则计数值加一并将当前线程阻塞在