Linux下C的线程同步机制

C里提供了保证线程安全性的三种方法:

(添加头文件#include<pthread.h>,pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a, 在编译中要加 -lpthread参数)

  • 互斥锁

  通过锁的机制实现线程间的互斥,同一时刻只有一个线程可以锁定它,当一个锁被某个线程锁定的时候,如果有另外一个线程尝试锁定这个临界区(互斥体),则第二个线程会被阻塞,或者说被置于等待状态。只有当第一个线程释放了对临界区的锁定,第二个线程才能从阻塞状态恢复运行。

  int pthread_mutex_init(pthread_mutex_t* mutex, const thread_mutexattr_t* mutexattr);初始化一个互斥锁。

  int pthread_mutex_lock(pthread_mutex_t* mutex);如果mutex被锁定,当前进程处于等待状态;否则,本进程获得互斥锁并进入临界区。

  int pthread_mutex_trylock(pthread_mutex_t* mutex);和lock不同的时候,尝试获得互斥锁不成功不会使得进程进入阻塞状态,而是继续返回线程执行。该函数可以有效避免循环等待锁,如果trylock失败可以释放已经占有的资源,这样可以避免死锁。

  int pthread_mutex_unlock(pthread_mutex_t* mutex);释放互斥锁,并使得被阻塞的线程获得互斥锁并执行。

  int pthread_mutex_destroy(pthread_mutex_t* mutex);用来撤销互斥锁的资源。

pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);

void pthread1(void* arg){
   pthread_mutex_lock(&mutex);
   .....//临界区
   pthread_mutex_unlock(&mutex);
}

void pthread2(void* arg){
   pthread_mutex_lock(&mutex);
   .....//临界区
   pthread_mutex_unlock(&mutex);
}
  • 读写锁

读写锁与互斥量类似,不过读写锁允许更高的并行性。适用于读的次数大于写的次数的数据结构。

一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。

读锁锁住,加读锁,可以;加写锁会被阻塞,但此时会阻塞后续的读锁请求,防止读锁长期占用无法进入写模式。写锁就是互斥锁。

int pthread_rwlock_init(pthread_rwlock_t* rwlock, const pthread_rwlockattr_t* attr);初始化读写锁

int pthread_destroy(pthread_rwlock_t* rwlock);销毁读写锁

int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock);加读锁

int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);加写锁

int pthread_rwlock_unlock(pthread_rwlock_t* rwlock);解锁

  • 条件变量

  信号量只有锁住和不锁两种状态,而且当条件变量和信号量一起使用时,允许线程以无竞争的方式等待特定的条件发生

  条件本身是由互斥量保护的:线程在改变条件状态之前必须先锁住互斥量。

  int pthread_cond_init(pthread_cond_t* cond,const pthread_condattr_t* attr);初始化动态分配的条件变量;也可以直接用PTHREAD_INITIALIZER直接赋值给静态的条件变量

  int pthread_cond_destroy(pthread_cond_t* cond)撤销条件变量资源;

  int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);使用该函数使得等待条件变量为真。线程被条件变量cond阻塞。

  int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex,const struct timespec* tspr);与wait类似,只是经历tspr时间后,即使条件变量不满足,阻塞也被解除,返回错误码。

  int pthread_cond_signal(pthread_cond_t* cond);唤醒因为条件变量阻塞的线程。

  int pthread_cond_broadcast(pthread_cond_t* cond);唤醒等待该条件的所有线程。

  

pthread_cond_t cond;
pthread_mutex_t mutex;
int count=0;
void pthread1(void* arg){
    pthread_mutex_lock(&mutex);
    while(count==0)
        pthread_cond_wait(&cond,&mutex);
    count--;
    pthread_mutex_unlock(&mutex);
}
void pthread2(void* arg){
    pthread_mutex_lock(&mutex);
    if(count==0)
        pthread_cond_signal(&cond);
    count++;
    pthread_mutex_unlock(&mutex);
}
  • 自旋锁

  互斥量阻塞线程的方式是使其进入睡眠,而自旋锁是让线程忙等,即不会使其睡眠,而是不断循判断自旋锁已经被解锁。

  适用于占用自旋锁时间比较短的情况。

  • 信号量

介绍一下POSIX(POSIX标准定义了操作系统应该为应用程序提供的接口标准,换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。)的信号量机制,定义在头文件/usr/include/semaphore.h

1)初始化一个信号量:sem_init()

int sem_init(sem_t* sem,int pshared,unsigned int value);

pshared为0时表示该信号量只能在当前进程的线程间共享,否则可以进程间共享,value给出了信号量的初始值。

2)阻塞线程

sem_wait(sem_t* sem)直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少;sem_trywait(sem_t* sem)是wait的非阻塞版本,它直接将sem的值减一,相当于P操作。

3)增加信号量的值,唤醒线程

sem_post(sem_t* sem)会使已经被阻塞的线程其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。相当于V操作。

3)释放信号量资源

sem_destroy(sem_t* sem)用来释放信号量sem所占有的资源

pthread_mutex_t mutex;
sem_t full,empty;

void producer(void* arg){
    while(1){
    sem_wait(&empty);//need to produce. the the empty of resource need minus 1
    pthread_mutex_lock(&mutex);
    ...//produce a resource
    pthread_mutex_unlock(&mutex);
    sem_post(&full); //have produced a resource, the the full of resource need add 1
    }
}
void consumer(void* arg){
    while(1){
    sem_wait(&full);
    pthread_mutex_lock(&mutex);
    ...//consume a resource
    pthread_mutex_unlock(&mutex);
    sem_post(&empty);
    }
}
时间: 2024-10-19 07:57:58

Linux下C的线程同步机制的相关文章

linux学习笔记之线程同步机制

一.基础知识. 1:线程同步机制:互斥量,读写锁,条件变量,自旋锁,屏障. 1,互斥量:每个进程访问被互斥量保护的资源时,都需要先对互斥量进行判断. 1)互斥量重要属性:进程共享属性,健壮属性,类型属性. 2)部分系统 不支持 进程共享属性 3)对互斥量重复加锁会导致死锁. 2,读写锁. 1)读写锁有3种状态:读模式加锁,写模式加锁,未加锁. 1-写加锁模式:任何加锁都会被阻塞. 2-读加锁模式:读模式加锁的任何线程都可以得到访问权,同时添加一个读模式锁.但,写模式加锁会被阻塞. 3-在读模式下

Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁

互斥锁通信机制 基本原理 互斥锁以排他方式防止共享数据被并发访问,互斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个互斥锁逻辑上绑定之后,对该资源的访问操作如下: (1)在访问该资源之前需要首先申请互斥锁,如果锁处于开状态,则申请得到锁并立即上锁(关),防止其他进程访问资源,如果锁处于关,则默认阻塞等待. (2)只有锁定该互斥锁的进程才能释放该互斥锁. 互斥量类型声明为pthread_mutex_t数据类型,在<bits/pthreadtypes.h>中有具体的定义. 互斥量

【转】Python线程同步机制: Locks, RLocks, Semaphores, Conditions, Events和Queues

Python线程同步机制: Locks, RLocks, Semaphores, Conditions, Events和Queues | Comments 翻译自Laurent Luce的博客原文名称:Python threads synchronization: Locks, RLocks, Semaphores, Conditions, Events and Queues原文连接:http://www.laurentluce.com/posts/python-threads-synchron

Linux 下进程与线程的基本概念

2019-10-01 关键字:进程.线程.信号量.互斥锁 什么是程序? 程序就是存放在磁盘上的指令和数据的有序集合,就是源代码编译产物. 它是静态的. 什么是进程? 进程就是操作系统为执行某个程序所分配的资源的总称.进程是程序的一次执行过程,因此它与程序不同,它是动态的.它的生命周期包括创建.调度.执行和消亡. 进程的内容主要包括以下三个部分: 1.正文段: 2.用户数据段: 3.系统数据段. 其中正文段与用户数据段两部分是从程序当中来的.而系统数据段则是操作系统分配的用来管理这个进程用的. 系

Linux系统开发9 线程同步

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

【总结】Java线程同步机制深刻阐述

原文:http://hxraid.iteye.com/blog/667437 我们可以在计算机上运行各种计算机软件程序.每一个运行的程序可能包括多个独立运行的线程(Thread). 线程(Thread)是一份独立运行的程序,有自己专用的运行栈.线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等. 当多个线程同时读写同一份共享资源的时候,可能会引起冲突.这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团. 同步这个词是从英文synchronize

多线程下的进程同步(线程同步问题总结篇)

之前写过两篇关于线程同步问题的文章(一,二),这篇中将对相关话题进行总结,本文中也对.NET 4.0中新增的一些同步机制进行了介绍. 首先需要说明的是为什么需要线程功能同步.MSDN中有这样一段话很好的解释了这个问题: 当多个线程可以调用单个对象的属性和方法时,对这些调用进行同步处理是非常重要的.否则,一个线程可能会中断另一个线程正在执行的任务,使该对象处于一种无效状态. 也就说在默认无同步的情况下,任何线程都可以随时访问任何方法或字段,但一次只能有一个线程访问这些对象.另外,MSDN中也给出定

linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np

=============================================================== linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主要有2个方法 1:利用linux系统自己的线程切换机制,linux有一个服务叫做irqbalance,这个服务是linux系统自带的,默认会启动,这个服务的作用就是把多线程平均分配到CPU的每个核上面,只要这个服务不停止,多线程分配就可以自己实现.但是要注意,如果线程函数内部的有某个循环,且该循环内

线程同步机制(二)-- 线程同步辅助类

我们在线程同步机制(一)--Synchronized和Lock简要介绍中学习了同步和临界区的概念,并且讨论了多个并发任务共享一个资源时的同步情况.访问共享资源的代码块叫临界区. 我们在线程同步机制(一)--Synchronized和Lock简要介绍中学习了一下内容: synchronized关键字 Lock接口及其实现类,如ReentrantLock,ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock 本章我们将学习如