线程的同步与互斥
2017-06-11 16:01
204 查看
线程的同步与互斥
线程的同步与互斥mutex (互斥量)
每个线程专属的私有空间,其中
上下文信息和
栈私有空间很是重要。
当多个线程在进程中运行时,他们看到同一份地址空间,这使得线程之间很容易的看到一份公共资源(临界资源),当多个线程看到同一份资源并对这份公共资源进行读写时,我们希望这份资源是原子性的,即我在使用这份资源时我不希望有其他执行流同时对这份资源进行读写操作。这就是为什么要引入线程的同步与互斥的原因。
mutex (互斥量)
多个线程同时访问共享数据时可能会冲突,例如 两个线程都要把某个全局变量增加1,这个操作在某平台需要三条指令完成:从内存读变量值到寄存器
4000
寄存器的值加1
将寄存器的值写回内存
假设两个线程在多处理器平台上同时执行这三条指令,则可能会导致错误的结果,比如说以下这种情况:
#include <stdio.h> #include <stdlib.h> #include <pthread.h> int g_val; int g_val; void* thread_val(void* arg) { int i = 0; while (i < 500000) { int tmp = g_val; g_val = tmp + 1; //printf("%d\n",g_val); i++; } } int main() { pthread_t id1, id2; pthread_create(&id1, NULL, thread_val, NULL); pthread_create(&id2, NULL, thread_val, NULL); pthread_join(id1, NULL); pthread_join(id2, NULL); printf("%d\n",g_val); return 0; }
我们想要的结果是线程1和线程2在运行完之后将g_val的值加到一百万。实现结果:
但明显并不能为什么呢
线程1刚把g_val从内存中取出来,准备对其运算,这时切换到另线程2,线程1会将g_val保存在他的上
下文信息中(每个线程有自己私有的上下文信息),回到线程2,如果他将g_val又从内存中取出来,在CPU上经过各种运算再把它放回内存。这时切换回线程1,因为线程一从CPU拿出来的变量保存在他的上下文信息中,所以在g_val被线程2改变后,线程1保存在上下文中的g_val并没有改变,线程1把g_val放入CPU,经过各种运算放回内存,这时线程2的工作就会被线程1覆盖。我们并不希望这样
对于多线程的程序,访问冲突的问题是很普遍的,解决的办法是引入
互斥锁(Mutex,Mutual Exclusive Lock),获得锁的线程可以完成“读-修改-写”的操作,然后释放锁给其它线程,没有获得
锁的线程只能等待而不能访问共享数据,这样“读-修改-写”三步操作组成一个
原子操作,要么都执行,要么都不执行,不会执行到中间被打断,也不会在其它处理器上并行做这个操作。
返回值:成功返回0,失败返回错误号。
pthread_mutex_init函数对Mutex做初始化,参数attr设定Mutex的属性,如果attr为NULL则表示缺省属性。
pthread_mutex_init函 数初始化的Mutex可以
用pthread_mutex_destroy销毁。如果Mutex变量是静态分配的(全局变量 或static变量),也
可以用宏定义PTHREAD_MUTEX_INITIALIZER
#include <stdio.h> #include <stdlib.h> #include <pthread.h> pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int g_val; void* thread_val(void* arg) { int i = 0; while (i < 500000) { pthread_mutex_lock(&lock);//lock here int tmp = g_val; g_val = tmp + 1; //printf("%d\n",g_val); pthread_mutex_unlock(&lock);//unlock here i++; } } int main() { pthread_t id1, id2; pthread_create(&id1, NULL, thread_val, NULL); pthread_create(&id2, NULL, thread_val, NULL); pthread_join(id1, NULL); pthread_join(id2, NULL); pthread_mutex_destroy(&lock);//destroy lock printf("%d\n",g_val); return 0; }
运行结果
相关文章推荐
- java基础——多线程(线程的同步互斥与通信)
- 多线程系列二——java线程间的互斥与同步
- 线程的同步与互斥
- linux下线程的同步和互斥
- 多线程篇(二)——线程之间的同步与互斥,关键段的使用
- Linux下的多线程编程二(线程的同步与互斥)
- 最近的一个作业(用c++模拟线程的同步和互斥)
- 【IO进程】守护进程,线程创建、同步与互斥
- 进程、线程知识点总结和同步(消费者生产者,读者写者三类问题)、互斥、异步、并发、并行、死锁、活锁的总结
- Android进程线程之同步互斥(一)
- 【UNIX】什么是线程的同步和互斥
- 高并发下的线程安全实现——互斥同步
- 线程之间的同步与互斥
- 【Java】线程并发、互斥与同步[转载]
- 线程间同步与互斥
- 操作系统 进程/线程 同步与互斥
- 线程常用函数 互斥 同步 ------笔记
- Linux线程浅析[线程的同步和互斥之线程同步的条件变量pthread_cond_t]
- 生产者与消费者模式(线程的同步与互斥)
- 【UNIX】通过线程的同步和互斥完成的AB循环