pthread 互斥量
参考文献:
温故知新
在 OS 中,每个进程都独立地拥有:
- Process ID, process group ID, user ID, and group ID
- Environment
- Working directory
- Program instructions
- Registers
- Stack
- Heap
- File descriptors
- Signal actions
- Shared libraries
- Inter-process communication tools (such as message queues, pipes, semaphores, or shared memory).
因此,使用 fork
开启一个新的进程,需要拷贝很多数据,开销较大。
与进程不同,线程需要只需要独立拥有:
- Stack pointer
- Registers
- Scheduling properties (such as policy or priority)
- Set of pending and blocked signals
- Thread specific data
需要特别注意的是,文件描述符和堆空间是进程独有的,因此该进程下面的所有线程都共用该进程的堆与文件描述符。
例如下面的代码:
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
void *worker1(void *arg)
{
char *p = malloc(25);
memcpy(p, "heap data from worker1", 23);
return p;
};
void *worker2(void *arg)
{
pthread_t tid1 = *(pthread_t *)arg;
char *ptr = NULL;
pthread_join(tid1, (void **)&ptr);
printf("In worker2: ");
if (ptr) puts(ptr);
return NULL;
}
int main()
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, worker1, NULL);
pthread_create(&tid2, NULL, worker2, &tid1);
pthread_join(tid2, NULL);
}
线程同步
在描述这个概念之前,先看一段代码:
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
const int N = 1e4;
int value = 0;
void *worker1(void *arg)
{
int i = 1;
for (; i <= N / 2; i++) value = value + i;
return NULL;
};
void *worker2(void *arg)
{
int i = N / 2 + 1;
for (; i <= N; i++) value = value + i;
return NULL;
}
int main()
{
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, worker1, NULL);
pthread_create(&tid2, NULL, worker2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d\n", value);
printf("SUM(1, %d) should be %d .\n", N, N * (N + 1) / 2);
}
显然,我们想通过 2 个线程实现 SUM(1, N)
这个功能,但是编译多次你会发现,value
的值并不准确,有时候能输出正确答案 500500
,有时候却不能。
这是因为 work1
和 work2
是并发执行的,假设一开始,2 个线程同时计算 value + i
,work1
和 work2
分别得到 1
和 5001
,但是写入 value
变量是有先后顺序的。假设 work1
先写入,work2
后写入,那么对于这 2 次累加,value
的最终结果是 5001
,而不是 5002
。
从这个例子可以看出,线程与进程类似,同样需要同步 (Synchronization) ,对于临界资源,每次只允许一个线程访问。
互斥量 mutex
互斥量,也叫互斥锁。mutex, 即 Mutual exclusion , 意为相互排斥,主要用于实现线程同步中的写保护操作。
pthread_mutex_init
初始化一个互斥量 pthread_mutex_t mutex
.
函数原型:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
参数:
mutex
是即将要被初始化的互斥量attr
是互斥量的属性,与pthread_attr_t
类似
与之类似的,还有 pthread_mutex_destroy
函数。
使用方法:
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
pthread_mutex_destroy(&mutex);
pthread_mutex_lock
阻塞调用。如果这个互斥锁此时正在被其它线程占用, 那么 pthread_mutex_lock()
调用会进入到这个互斥锁量的等待队列中,并会进入阻塞状态, 直到拿到该锁之后才会返回。
函数原型如下:
int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_trylock
非阻塞调用。当请求的锁正在被占用的时候, 不会进入阻塞状态,而是立刻返回,并返回一个错误代码 EBUSY,意思是说, 有其它线程正在使用这个锁。
直白点的说法,请求资源,能拿到就拿,拿不到我就继续往下执行。
函数原型:
int pthread_mutex_trylock(pthread_mutex_t *mutex);
pthread_mutex_unlock
释放互斥锁。
函数原型如下:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
对于这些 API,如果成功,那么返回 0,否则返回错误码 errno
,可以通过下列宏定义打印错误信息:
#define handler_error_en(en, msg) \
do \
{ \
errno = en; \
perror(msg); \
exit(EXIT_FAILURE); \
} while (0)
例子:同步累加
对于「线程同步」一节给出的例子,使用互斥量实现同步操作,使得程序能够正确完成累加操作。
#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
const int N = 1e4;
int value = 0;
pthread_mutex_t mutex;
void *worker1(void *arg)
{
int i = 1;
int sum = 0;
for (; i <= N / 2; i++) sum += i;
// 这样保证 value 仅能由一个线程访问
pthread_mutex_lock(&mutex);
value += sum;
pthread_mutex_unlock(&mutex);
return NULL;
};
void *worker2(void *arg)
{
int i = N / 2 + 1;
int sum = 0;
for (; i <= N; i++) sum += i;
pthread_mutex_lock(&mutex);
value += sum;
pthread_mutex_unlock(&mutex);
return NULL;
}
int main()
{
pthread_t tid1, tid2;
pthread_mutex_init(&mutex, NULL);
pthread_create(&tid1, NULL, worker1, NULL);
pthread_create(&tid2, NULL, worker2, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("%d\n", value);
printf("SUM(1, %d) should be %d .\n", N, N * (N + 1) / 2);
pthread_mutex_destroy(&mutex);
}
pthread 互斥量的更多相关文章
- pthread中互斥量,锁和条件变量
互斥量 #include <pthread.h> pthread_mutex_t mutex=PTHREAD_MUTEX_INTIIALIZER; int pthread_mutex_in ...
- php Pthread 多线程 (三) Mutex 互斥量
当我们用多线程操作同一个资源时,在同一时间内只能有一个线程能够对资源进行操作,这时就需要用到互斥量了.比如我们对同一个文件进行读写操作时. <?php class Add extends Thr ...
- Linux/Unix 线程同步技术之互斥量(1)
众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...
- Linux 多线程互斥量互斥
同步 同一个进程中的多个线程共享所在进程的内存资源,当多个线程在同一时刻同时访问同一种共享资源时,需要相互协调,以避免出现数据的不一致和覆盖等问题,线程之间的协调和通信的就叫做线程的同步问题, 线程同 ...
- linux线程同步(1)-互斥量
一.概述 互斥量是线程同步的一种机制,用来保护多线程的共享资源.同一时刻,只允许一个线程对临界区进行 ...
- [转]一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程
一个简单的Linux多线程例子 带你洞悉互斥量 信号量 条件变量编程 希望此文能给初学多线程编程的朋友带来帮助,也希望牛人多多指出错误. 另外感谢以下链接的作者给予,给我的学习带来了很大帮助 http ...
- 共享内存+互斥量实现linux进程间通信 分类: Linux C/C++ 2015-03-26 17:14 67人阅读 评论(0) 收藏
一.共享内存简介 共享内存是进程间通信中高效方便的方式之一.共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针,两个进程可以对一块共享 ...
- [linux basic 基础]----同步互斥量
互斥量,运行程序元锁住某个对象,使得每次只能有一个线程访问它:为了控制对关键代码的访问,必须在进入这段代码之前锁住一个互斥量,然后在完成操作之后解锁它 :基本函数与用于信号量的函数非常相似#inclu ...
- 【Linux】Mutex互斥量线程同步的例子
0.互斥量 Windows下的互斥量 是个内核对象,每次WaitForSingleObject和ReleaseMutex时都会检查当前线程ID和占有互斥量的线程ID是否一致. 当多次Wait**时就 ...
随机推荐
- leetcode103:permutations-ii
题目描述 给出一组可能包含重复项的数字,返回该组数字的所有排列 例如: [1,1,2]的排列如下: [1,1,2],[1,2,1], [2,1,1]. Given a collection of nu ...
- Frontpage 三种回车键
Frontpage的回车键有三种:enter.shift+enter.ctrl+enter. enter键对应于HTML中的<p></p>,是一个段落的分界符. shift+e ...
- Core WebApi项目快速入门(二):Filter详解
Core的核心是DI,面向AOP的编程方式.在.NetCore中AOP的实现很大程度上依赖于Filter.下面就Core WebApi中的Filter进行举例. 其中鉴权中心我个人认为是比较重要的概念 ...
- VBA_50段代码总结
'' 30个有用的VBA代码 '目录: '1--合理使用数组:'2--一次保存并关闭所 ...
- post和get、PostMapping、GetMapping和RequestMapping
PostMapping.GetMapping和RequestMapping PostMapping和GetMapping封装了method="",限制了method,更加规范化. ...
- high Performance
目的 找出系统性能瓶颈(包括硬件瓶颈和软件瓶颈): 提供性能优化的方案(升级硬件?改进系统系统结构?): 达到合理的硬件和软件配置: 使系统资源使用达到最大的平衡. CPU过渡使用会造成大量进程等待C ...
- sock skbuf 结构:
/** * struct sock - network layer representation of sockets * @__sk_common: shared layout with inet_ ...
- tcp 输入 prequeue以及backlog队列
/*ipv4_specific是TCP传输层到网络层数据发送以及TCP建立过程的真正OPS, 在tcp_prot->init中被赋值给inet_connection_sock->icsk_ ...
- 创建一个自定义名称的Ceph集群
前言 这里有个条件,系统环境是Centos 7 ,Ceph 的版本为Jewel版本,因为这个组合下是由systemctl来进行服务控制的,所以需要做稍微的改动即可实现 准备工作 部署mon的时候需要修 ...
- Spring @Autowired 注解自动注入流程是怎么样?
面试中碰到面试官问:"Spring 注解是如果工作的?",当前我一惊,完了这不触及到我的知识误区了吗?,还好我机智,灵机一动回了句:Spring 注解的工作流程倒还没有看到,但是我 ...