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 ... 
随机推荐
- 保存进程的pid 文件目录/var/run/
			http://blog.ddup.us/?p=110 http://blog.csdn.net/fyinsonw/article/details/4113124 首先声明这不是愚人节消息,事实上这个消 ... 
- docvalue and fielddata
			大部分字段类型默认被索引的(inverted index),可以被搜索search: 哪个文档有这个词sort&aggregations: look up the document and f ... 
- GO基本数据结构练习:数组,切片,映射
			按<GO IN ACTION>的书上进行. 应该是第二次了哦~~ package main import ( "fmt" ) func main() { array : ... 
- 安卓使用WebView清除缓存
			原文:https://blog.csdn.net/liwei123liwei123/article/details/52624826 Android 清除WebView缓存 最近项目中需要用WebVi ... 
- DotNetOpenAuth实践之WebApi资源服务器
			系列目录: DotNetOpenAuth实践系列(源码在这里) 上篇我们讲到WCF服务作为资源服务器接口提供数据服务,那么这篇我们介绍WebApi作为资源服务器,下面开始: 一.环境搭建 1.新建We ... 
- js求区间随机数
			function rnd(n, m){ var random = Math.round(Math.random()*(m-n)+n); return random; } 
- ios safari input fixed 软键盘里的爱恨情仇
			请看第一题: 为什么我的input获取焦点后,被输入法遮住了. 解决办法: 源码: <!DOCTYPE html> <html lang="en"> < ... 
- CentOS7 安装 chrome-gnome-shell
			1.download https://gitlab.gnome.org/GNOME/chrome-gnome-shell 2.安装cmake和jq yum install -y cmake yum i ... 
- 报错org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet"
			org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n ... 
- windows下怎样使用md命令一次建立多级子目录
			在Windows系统中一次只能够创建一个子目录,在命令提示符窗口则可以一次性创建多个子目录,例如如果想在f盘创建多级子目录,则md 23\13\65\45,后面的数字随便都可以.如果想一次性删除多级目 ... 
