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时间结构体和获得时间函数
关于Linux下时间编程的问题: 1. Linux下与时间有关的结构体 struct timeval { int tv_sec; int tv_usec; }; 其中tv_sec是由凌晨开始算起的秒数 ...
- jquery 修改样式
//显示待办数字 function showdb(url,ID) { jQuery.get(url,function(data,status){ if(!isNaN(data)) { if(da ...
- 写在Web考试后的一点小总结
在实验室折腾附加题折腾了一个多钟没做出来……晚上回到宿舍决定再试一试,按原来的思路居然行了,目测在实验室的时候什么地方打错字了吧(心在流血) 实现晃过元素后出现跟随鼠标的悬浮窗,只有几行代码给我折腾了 ...
- 解析kubernetes架构
一. 简介: kubernetes是一个开源的容器管理工具,是基于GO语言开实现的,轻量级和便携式的应用,可以把kubernetes cluster在linux主机上部署.管理和扩容docker容器的 ...
- Java 中 List 向前和向后遍历
Java 中 List 向前和向后遍历 import java.util.*; public class TestCollectionIterator { public static void mai ...
- 获取 web 项目的绝对路径
获取 web 项目的绝对路径 <% String path = request.getContextPath(); String basePath = request.getScheme()+& ...
- centos7.5 ab压力测试安装和swoole压力测试
Apache Benchmark(简称ab) 是Apache安装包中自带的压力测试工具 ,简单易用 1.ab安装 yum -y install httpd-tools 2.ab参数详解,传送门:htt ...
- vars 变量预解析
JavaScript中,你可以在函数的任何位置声明多个var语句,并且它们就好像是在函数顶部声明一样发挥作用,这种行为称为 hoisting(悬置/置顶解析/预解析).当你使用了一个变量,然后不久在函 ...
- PHP 5.4.0之Traits
[PHP之Traits] As of PHP 5.4.0, PHP implements a method of code reuse called Traits. 1.Traits基础 2.优先级: ...
- python爬虫实战(三)--------搜狗微信文章(IP代理池和用户代理池设定----scrapy)
在学习scrapy爬虫框架中,肯定会涉及到IP代理池和User-Agent池的设定,规避网站的反爬. 这两天在看一个关于搜狗微信文章爬取的视频,里面有讲到ip代理池和用户代理池,在此结合自身的所了解的 ...