Linux/UNIX线程(2)
线程(2)
线程同步
当多个控制线程共享同样内存时,须要确保每一个线程看到一致的数据视图。假设每一个线程使用的变量都是其它线程不会读取或改动的,那么就不在一致性问题。
当两个或多个线程试图在同一时间改动同一变量时,也须要进行同步。考虑变量递增操作的情况:增量操作通常分三步:
1. 从内存单元读入寄存器
2. 在寄存器中进行变量值的添加
3. 把新的值写回内存单元
相互排斥量
能够通过使用pthread的相互排斥接口保护数据,确保同一时间仅仅有一个线程訪问数据。相互排斥量从本质上说是一把锁,在訪问资源前对相互排斥量加锁,在訪问完毕后释放相互排斥量上的锁。
对相互排斥量进行加锁以后,不论什么其它试图再次对相互排斥量加锁的线程将会被堵塞直到线程释放该相互排斥锁。
相互排斥变量用pthread_mutex_t数据类型来表示。在使用相互排斥量曾经。必须首先对其进行初始化。能够把它置为PTHREAD_MUTEX_INITIALIZER(仅仅对静态分配的相互排斥量),也能够通过调用pthread_mutex_init函数进行初始化。假设动态分配相互排斥量。那么释放内存前须要调用pthread_mutex_destroy。
用默认属性初始化相互排斥量,仅仅须要把attr设置为NULL。
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,constpthread_mutexattr_t *restrict attr);
intpthread_mutex_destroy(pthread_mutex_t *mutex);
,错误返回错误编号。
对相互排斥量进行加锁,须要调用pthread_mutex_lock,假设相互排斥量已经上锁,调用线程将堵塞直到相互排斥量被解锁。
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock( pthread_mutex_t *mutex );
int pthread_mutex_unlock(pthread_mutex_t *mutex);
,错误返回错误编号。
。否则pthread_mutex_trylock就会失败。不能锁住相互排斥量。而返回EBUSY。
避免死锁
假设线程试图对同一个相互排斥量加锁两次,那么它自身就会陷入死锁状态。
假设程序中使用多个相互排斥量时,假设同意一个线程一直占有第一个相互排斥量,而且试图锁住第二个相互排斥量时处于堵塞状态。可是游泳第二个相互排斥量的线程也试图锁住第一个相互排斥量,这是就会发生死锁。
能够通过小心地控制相互排斥量加锁的顺序来避免死锁的发生。仅仅有一个线程试图以与还有一个线程相反的顺序锁住相互排斥量时,才可能出现死锁。
读写锁
读写锁有三种状态:度模式下加锁状态。写模式下加锁状态,不加锁状态。一次仅仅有一个线程能够占用写模式的读写锁。可是多个线程能够同一时候占用读模式的读写锁。
读写锁很适合于对数据结构读的次数远大于写的情况。读写锁也叫做共享——独占锁。当读写锁以读模式锁住时,它是以共享模式锁住的;当它以写模式锁住时,它是以独占模式锁住的。
与相互排斥量一样,读写锁在使用之前必须初始化。在释放它们底层的内存前必须销毁。
#include <pthread.h>
intpthread_rwlock_init(pthread_rwlock* restrict rwlock, const pthread_rwlockattr_t* restrict attr);
int pthread_rwlock_destroy(pthread_rwlock_t* rwlock);
要在读模式下锁定读写锁,须要调用pthread_rwlock_rdlock;要在写模式下锁定读写锁。须要调用pthread_rwlock_wrlock。无论以何种方式锁住读写锁。都能够调用pthreead_rwlock_unlock进行解锁。
#include <pthread.h>
intpthread_rwlock_rdlock(pthread_rwlock_t* rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t* rwlock);
,否则返回错误编号
#include <pthread.h>
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock);
条件变量
条件变量是线程可用的还有一种同步机制。
条件变量给多线程提供了一个回合的场所。条件变量与相互排斥量一起使用时,同意线程以无竞争的方式等待特定的条件发生。
条件本身是由相互排斥量保护的。
线程在改变条件状态前必须首先锁住相互排斥量。其它线程在获得相互排斥量之前不会觉察到这样的改变。由于必须锁定相互排斥量以后才干计算条件。
条件变量使用之前必须首先进行初始化,pthread_cond_t数据类型代表的条件变量以两种方式进行初始化。能够把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,可是假设条件变量时动态分配的,能够使用pthread_cond_init函数进行初始化。
在释放底层的内存空间之前。能够使用pthread_cond_destroy函数对条件变量进行去初始化。
#include <pthread.h>
int pthread_cond_init (pthread_cond_t* restrict cond,pthread_condattr_t * restrict attr);
int pthread_cond_destroy (pthread_cond_t* cond);
除非须要创建一个非默认属性的条件变量,否则pthread_cond_init函数的attr參数能够设置NULL。
使用pthread_cond_wait等待条件变为真,假设在给定时间内条件不能满足,那么会生成一个代表出错误码的返回值。
intpthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
intpthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, conststruct timespec *abstime)
条件等待pthread_cond_wait()和计时等待pthread_cond_timedwait(),当中计时等待方式假设在给定时刻前条件没有满足。则返回ETIMEOUT。结束等待,当中abstime以与time()系统调用相允许义的绝对时间形式出现。0表示格林尼治时间1970年1月1日0时0分0秒。
不管哪种等待方式。都必须和一个相互排斥锁配合。以防止多个线程同一时候请求pthread_cond_wait()(或pthread_cond_timedwait()。下同)的竞争条件(RaceCondition)。
mutex相互排斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),而在更新条件等待队列曾经,mutex保持锁定状态,并在线程挂起进入等待前解锁。在条件满足从而离开pthread_cond_wait()之前,mutex将被又一次加锁,以与进入pthread_cond_wait()前的加锁动作相应。
Linux/UNIX线程(2)的更多相关文章
- Linux/Unix 线程同步技术之互斥量(1)
众所周知,互斥量(mutex)是同步线程对共享资源访问的技术,用来防止下面这种情况:线程A试图访问某个共享资源时,线程B正在对其进行修改,从而造成资源状态不一致.与之相关的一个术语临界区(critic ...
- Linux/UNIX线程(1)
线程(1) 本文将介绍怎样使用多个控制线程在单个进程环境中运行多个任务. 一个进程中的全部线程都能够訪问该进程的组成部件(如文件描写叙述符和内存). 线程包含了表示进程内运行环境必须的信息,当中包含进 ...
- 学习linux/unix编程方法的建议(转)
假设你是计算机科班出身,计算机系的基本课程如数据结构.操作系统.体系结构.编译原理.计算机网络你全修过 我想大概可以分为4个阶段,水平从低到高从安装使用=>linux常用命令=>linux ...
- Linux Unix 环境变量设置实例
背景 从第一次写Hello World我们便开始接触环境变量.这最基础的系统设置是必须要掌握的,尤其在是Linux/Unix系统中.比如,哪天某个Java进程出现问题,我们想分析一下其线程堆栈,却发现 ...
- 《Linux/Unix系统编程手册》读书笔记7 (/proc文件的简介和运用)
<Linux/Unix系统编程手册>读书笔记 目录 第11章 这章主要讲了关于Linux和UNIX的系统资源的限制. 关于限制都存在一个最小值,这些最小值为<limits.h> ...
- 《Linux/Unix系统编程手册》读书笔记2
<Linux/Unix系统编程手册>读书笔记 目录 第5章: 主要介绍了文件I/O更深入的一些内容. 原子操作,将一个系统调用所要完成的所有动作作为一个不可中断的操作,一次性执行:这样可以 ...
- Linux编程---线程
首先说一下线程的概念.事实上就是运行在进程的上下文环境中的一个运行流.普通进程仅仅有一条运行流,可是线程提供了多种运行的路径并行的局面. 同一时候,线程还分为核心级线程和用户级线程.主要差别在属于核内 ...
- 《Linux/Unix系统编程手册》 时间子系统
Linux下操作系统编程有两本经典APUE即<Advanced Programming in the UNIX Environment>和TLPI<The Linux Program ...
- 《Linux/UNIX系统编程手册》第63章 IO多路复用、信号驱动IO以及epoll
关键词:fasync_helper.kill_async.sigsuspend.sigaction.fcntl.F_SETOWN_EX.F_SETSIG.select().poll().poll_wa ...
随机推荐
- Linux 不常用命令总结
1. vim编辑模式下,搜索,/user,跳转下一个,小写的n 2.
- POJ 2752 Seek the Name, Seek the Fame(KMP求公共前后缀)
题目链接:http://poj.org/problem?id=2752 题目大意:给你一串字符串s找到所有的公共前后缀,即既是前缀又是后缀的子串. 解题思路: 如图所示 假设字符串pi与jq为符合条件 ...
- Base64的好处
1. 昨天的<MIME笔记>中提到,MIME主要使用两种编码转换方式----Quoted-printable和Base64----将8位的非英语字符转化为7位的ASCII字符. 虽然这样的 ...
- ceph存储池基本管理
一,设置默认存储池的pg或pgp的值(推荐100左右),在ceph.conf文件里增加: osd pool default pg num = osd pool default pgp num = 二, ...
- jquery的一个模板引擎-zt
jQuery-jTemplate.js下载:http://jtemplates.tpython.com/ 一 , 简单介绍 它是一个基于jQuery开发的javascript模板引擎.它主要的作用如下 ...
- Java 中(静态)变量、(静态)代码块的执行顺序
Java 中(静态)变量.(静态)代码块的执行顺序 非原创 本文讨论 Java 中(静态)变量.(静态)代码块的执行顺序 首先创建 3 个类 1.Foo 类 public class Foo { pu ...
- docker-compose RabbitMQ与Nodejs接收端同时运行时的错误
首先讲一下背景: 我现在在开发的一个项目,需要运行RabbitMQ和Nodejs接收端(amqplib库),但是在Nodejs接收端运行时,无法连接至RabbitMQ端,经常提示说 connect E ...
- 洛谷P2471 [SCOI2007] 降雨量 [RMQ,模拟]
题目传送门 降雨量 题目背景 07四川省选 题目描述 我们常常会说这样的话:“X年是自Y年以来降雨量最多的”.它的含义是X年的降雨量不超过Y年,且对于任意Y<Z<X,Z年的降雨量严格小于X ...
- Android之 内容提供器(1)——使用内容提供器访问其它程序共享的数据
(下面内容是阅读郭霖大神的<第一行代码>总结的) 1 概述 内容提供器是Android实现跨程序共享数据的标准方式. 内容提供器的的使用方法有两种, 一是使用已有的内容提供器对其他程序的数 ...
- React Native升级方法——升级到最新版本0.59
React Native最近有大动作,于2019年3月12日发布新版本0.59.主要有两点值得升级:支持React Hooks:升级了JavaScriptCore,使Android性能有大幅提升.据用 ...