互斥锁

互斥锁是线程之间最基本的同步形式,用于保护临界区,任意时刻只能有一个线程在临界区中执行。
初始化

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t *attr);
  • mutex:初始化锁的标识符
  • attr:锁的属性,如果设置为NULL,则使用系统默认的

加锁

#include <pthread.h>int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
  • mutex:锁的标识符

lock作用是给数据加锁,如果已经有线程给当前数据块加锁了,那么当前线程阻塞,直到上一个线程给代码解锁,然后当前线程唤醒,继续加锁。注意唤醒的过程是自动的,不需要写代码执行。

try_locklock的非阻塞形式,如果成功加锁,返回0;失败返回有关的错误码。

解锁

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
  • mutex:锁的标识符
    对加锁的数据进行解锁。

条件变量

经典的waitsignal操作,具体参照操作系统,在这里仅学习Linux\Unix中的操作。

初始化和销毁条件变量

#include <pthread.h>int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
  • cond:条件变量的标识符
  • attr:条件变量的属性,设置为NULL则使用系统默认的

wait操作

#include <pthread.h>int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,const struct timespec *abstime);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
  • cond:条件变量
  • mutex:互斥锁,需要进行wait的代码片段
  • abstime:等待时间

signal操作

#include <pthread.h>int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
  • cond:条件变量标识符

signal表示唤醒一个阻塞的线程,broad_cast表示唤醒所有的阻塞线程。如果唤醒一个,则根据线程优先级和有关的调度策略执行操作。

一些其它的

线程的属性、互斥量的属性、条件变量的属性可以通过有关的函数进行设置,具体参照手册。

代码实例

生产者线程向缓冲池中填充数据,消费者线程从缓冲区中读取数据。参照《Unix网络编程第二卷》,设计了一个新的结构。要明确,因为互斥量和锁必须同时出现,所以专门设计了一个结构Ready用于waitsignal操作。但是生产者不用进行waitsignal操作,只需要添加货物的时候进行互斥,所以单独提取出来。需要注意的是,一定要记得解锁操作,否则会发生死锁阻塞。

#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <random>
#include <queue>// 随机数引擎
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> disCargo(0, 20);
std::uniform_int_distribution<> disTime(0, 3);const int CONSUMER_NUM = 5;
const int PRODUCER_NUM = 3;
const int CARGO_NUM = 10;bool stop = false;std::vector<pthread_t> consumerThreads;
std::vector<pthread_t> producerThreads;// 生产者放置货物使用的互斥量
struct Cargo {pthread_mutex_t mutex;std::queue<int> buffer;
} cargoTag;// 消费者可以消费的条件变量
struct Ready {pthread_mutex_t mutex;pthread_cond_t cond;
} readyTag;void *consume(void *);
void *produce(void *);int main() {pthread_mutex_init(&cargoTag.mutex, nullptr);pthread_mutex_init(&readyTag.mutex, nullptr);pthread_cond_init(&readyTag.cond, nullptr);for (int i = 0; i < PRODUCER_NUM; ++i) {pthread_t num;pthread_create(&num, nullptr, &produce, &i);producerThreads.push_back(num);}for (int i = 0; i < CONSUMER_NUM; ++i) {pthread_t num;pthread_create(&num, nullptr, &consume, &i);consumerThreads.push_back(num);}for (const auto &it: producerThreads) {pthread_join(it, nullptr);}for (const auto &it: consumerThreads) {pthread_join(it, nullptr);}return 0;
}void *produce(void *arg) {pthread_t num = *(pthread_t *) arg;while (!stop) {int t = disTime(gen);int no = disCargo(gen);sleep(t);  //  模拟生产使用的时间// 生产货物加锁,一定要注意顺序,防止出现死锁pthread_mutex_lock(&readyTag.mutex);pthread_mutex_lock(&cargoTag.mutex);printf("producer %ld produce cargo %d use %d s\n", (long) num, no, t);cargoTag.buffer.push(no);pthread_mutex_unlock(&cargoTag.mutex);pthread_mutex_unlock(&readyTag.mutex);pthread_cond_signal(&readyTag.cond);  // 通知消费者}
}void *consume(void *arg) {pthread_t num = *(pthread_t *) arg;while (!stop) {pthread_mutex_lock(&readyTag.mutex);if (cargoTag.buffer.empty()) {pthread_mutex_unlock(&readyTag.mutex);  // 一定要先解锁pthread_cond_wait(&readyTag.cond, &readyTag.mutex);} int no = cargoTag.buffer.front();cargoTag.buffer.pop();pthread_mutex_unlock(&readyTag.mutex);    // 一定要解锁int t = disTime(gen);sleep(t);printf("consumer %ld consume cargo %d use %d s\n", (long) num, no, t);}
}

补充一个C++11的代码实例:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <unistd.h>
#include <random>
#include <queue>
#include <signal.h>
#include <cstring>// 随机数引擎
std::random_device rd;
std::mt19937 gen (rd() );
std::uniform_int_distribution<> disCargo (0, 20);
std::uniform_int_distribution<> disTime (0, 3);std::vector<std::thread> producerThreads;
std::vector<std::thread> consumerThreads;struct Buffers {std::queue<int> buf;std::mutex mtx;
} buffer;std::mutex mtxCon;std::condition_variable condCon;bool stop = false;void produce (int id) {while (!stop) {int t = disTime (gen);int no = disCargo (gen);std::this_thread::sleep_for (std::chrono::duration<int, std::milli>(1000 * t));mtxCon.lock();buffer.mtx.lock();buffer.buf.push (no);buffer.mtx.unlock();mtxCon.unlock();condCon.notify_one();  // 唤醒一个消费者printf ("producer id %d generates cargo %d after %d seconds\n", id, t, no);}printf("producer %id stops............\n");
}void consume (int id) {while (!stop) {int no = 0;{std::unique_lock<std::mutex> lock (buffer.mtx);condCon.wait (lock, [&buffer]() {return !buffer.buf.empty();});no = buffer.buf.front();}buffer.buf.pop();int t = disTime(gen);printf("consumer id %d gets cargo %d and will sleep for %d seconds\n", id, no, t);std::this_thread::sleep_for (std::chrono::duration<int, std::milli>(1000 * t));}printf("consumer %id stops............\n");
}void handleSignal(int sig) {if (sig != SIGINT) {return;}puts("get signal SIGINT.........................");stop = true;
}int main() {struct sigaction sa;bzero(&sa, sizeof(sa));sa.sa_handler = handleSignal;sa.sa_flags = SA_RESTART;if (sigaction(SIGINT, &sa, nullptr) == -1) {perror("sigaction error\n");return 1;}for (int i = 0; i < 10; ++i) {producerThreads.emplace_back(std::thread(&produce, i));consumerThreads.emplace_back(std::thread(&consume, i));}for (auto &th: producerThreads) {th.join();}for (auto &th: consumerThreads) {th.join();}return 0;
}

Linux\Unix线程的互斥锁和条件变量相关推荐

  1. Linux下多线程编程互斥锁和条件变量的简单使用

    Linux下的多线程遵循POSIX线程接口,称为pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,链接时需要使用库libpthread.a.线程是进程的一个实体,是CPU ...

  2. Linux C 多线程编程----互斥锁与条件变量-转

    转:http://blog.csdn.net/xing_hao/article/details/6626223 一.互斥锁 互斥量从本质上说就是一把锁, 提供对共享资源的保护访问. 1. 初始化: 在 ...

  3. Linux多线程编程---线程间同步(互斥锁、条件变量、信号量和读写锁)

    本篇博文转自http://zhangxiaoya.github.io/2015/05/15/multi-thread-of-c-program-language-on-linux/ Linux下提供了 ...

  4. linux线程(互斥锁、条件)

    线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...

  5. 非常精简的Linux线程池实现(一)——使用互斥锁和条件变量

    https://blog.csdn.net/kxcfzyk/article/details/31719687 线程池的含义跟它的名字一样,就是一个由许多线程组成的池子. 有了线程池,在程序中使用多线程 ...

  6. linux线程间同步(1)互斥锁与条件变量

    线程的最大特点是资源的共享性,但资源共享中的同步问题是多线程编程的难点.linux下提供了多种方式来处理线程同步,最常用的是互斥锁.条件变量和信号量以及读写锁. 互斥锁(mutex) 互斥锁,是一种信 ...

  7. Linux系统编程:使用mutex互斥锁和条件变量实现多个生成者和消费者模型

    实现代码 如题,使用mutex互斥锁和条件变量实现多个生成者和消费者模型. 直接上代码,需要线程中的互斥锁和条件变量的相关知识进行支撑.这里就不细说了呀,代码中有一定的注释. #include < ...

  8. 信号量,互斥锁,条件变量的联系与区别

    转自:http://blog.chinaunix.net/u3/108685/showart_2127853.html 信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程, ...

  9. 【C++】多线程互斥锁、条件变量

    我们了解互斥量和条件变量之前,我们先来看一下为什么要有互斥量和条件变量这两个东西,了解为什么有这两东西之后,理解起来后面的东西就简单很多了!!! 先来看下面这段简单的代码: int g_num = 0 ...

最新文章

  1. 在linux命令行 下学习编写java
  2. html数据分析表格api_Python数据分析基本库——Matplotlib(一)
  3. android listview settag,Android View中setTag的二三事
  4. php编译自己库文件,php编译后追加库模块-gd库
  5. Python操作HDF5存储数据方法总结
  6. Linux下安装配置Jenkins
  7. MySql单表的curd-02
  8. NUMA - Non Uniform Memory Architecture 非统一内存架构
  9. 比Excel制图更强大,Python可视化工具Altair入门教程
  10. Java中HashMap和TreeMap的区别深入理解
  11. 苹果软件App上架问题
  12. paip.web service技术在 JAVA与.NET中的应用流程方案
  13. 用C++ Builder对图像进行特殊效果处理
  14. dialog下textarea滚动条不显示
  15. sscanf_s函数
  16. Java实现QQ机器人
  17. 走进CIM,开启智慧城市的全生命周期管理
  18. js 正则 验证密码输入,必须为6-15位,含有数字字母,或者符号
  19. 计算机二级word邀请函制作步骤,利用邮件合并制作邀请函(2)
  20. Andriod PDA RFID感应盘点

热门文章

  1. long类型转成integer类型避免空指针的方法_解决swagger的类型转换报错问题
  2. 渗透测试岗位面试题(渗透思路)
  3. 分拆素数和【筛选法】
  4. 对于electron-react-boilerplate(ERB)的学习笔记(legacy)
  5. tensorflow中的sequence_loss_by_example
  6. 获取北京时间授时api stm32 esp8266获取北京时间、年月日、星期api GMT格林威时间转换北京时间
  7. 动态规划,java实现算法导论15章钢条切割
  8. 区分PO,VO,DAO,BO,POJO
  9. 灭霸—个人冲刺(5)
  10. 随机初始化(代码实现)