POSIX线程互斥量的使用——pthreads线程库实例笔记3
2010-07-17 15:30
525 查看
Mutex Variables(互斥量)
Mutex(互斥量)是“mutual exclusion”的缩写,互斥量最主要的用途是在多线程中对共享数据同进行写操作时同步线程并保护数据。
互斥量在保护共享数据资源时可以把它想象成一把锁,在Pthreads库中互斥量最基本的设计思想是在任一时间只有一个线程可以锁定(或拥有)互斥量,因此,即使许多线程尝试去锁定一个互斥量时成功的只会有一个,只有在拥有互斥量的线程开锁后其它的线程才能锁定,就是说,线程必须排队访问被保护的数据。
互斥量常被用来防止竞争条件(race conditions),下面是一个涉及银行业务的竞争条件案例:
在上面的案例中,当线程使用共享数据资源Banlance时,互斥量会锁定“Balance”,如果不锁定,就会像表内情况一样,Balance的计算结果会混乱。
拥有互斥量的线程常常做的一个事情就是更改全局变量值,这是一个安全方法,确保在多个线程更改同一个变量时,它最终的值与唯一一个线程执行更改操作后的结果是一致的,这个被更改的变量属于一个临界区(critical section)。
使用互斥量的一个标准的过程是:
创建并初始化互斥量;
多个线程试图锁定此互斥量;
有且只有一个线程成功的拥有了这个互斥量;
拥有互斥量的线程执行了一系列的操作;
拥有互斥量的线程解锁互斥量;
另一个线程获得此互斥量,并重复上面的过程;
最终互斥量被销毁。
当许多线程竞争一个互斥量时,在请求时失败的线程会阻塞——无阻塞的请求是用“trylock”而不是用“lock”,所以pthread_mutex_trylock()与pthread_mutex_lock()的区别就是在互斥量还没有解锁的情况下,前者不会阻塞线程。
在保护共享数据时,程序员的责任是确定每个线程需要用到互斥量,例如,如果有4个线程正在更改同一个数据,但是只有一个线程使用了互斥量,那么这个数据仍然会损坏。
创建并销毁互斥量
函数:
pthread_mutex_init (mutex,attr)
pthread_mutex_destroy (mutex)
pthread_mutexattr_init (attr)
pthread_mutexattr_destroy (attr)
用法:
互斥量必须要声明为pthread_mutex_t类型,并且在使用之前必须要被初始化。有两种方法初始化互斥量:
静态初始化,例如:pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
动态初始化,使用pthread_mutex_init()过程,此函数可以设置互斥量属性对象attr;
注意,互斥量初始状态是未被锁定的(unlocked)。
对象attr常被用来设置互斥量对象的属性值的,而且必须是pthread_mutexattr_t类型(默认值是NULL)。Pthreads标准定义了3个互斥量可设置选项:
Protocol:为互斥量指定用来防止优先级倒置的规则的;
Prioceiling:为互斥量指定优先级上限的;
Process-shared:为互斥量指定进程共享的。
注意,不是所有的实现都要提供这三个可选的互斥量属性的。
pthread_mutexattr_init()和pthread_mutexattr_destroy()函数分别是用来创建和销毁互斥量属性的。
pthread_mutex_destroy()在互斥量不再被需要时,用来释放互斥量对象。
锁定和解锁互斥量
函数:
用法:
线程用pthread_mutex_lock()函数通过指定的互斥量获得一个锁,如果互斥量已经被另一个线程锁定,那么这个请求会阻塞申请的线程,直到互斥量解锁。
pthread_mutex_trylock()尝试锁定互斥量,然而,如果互斥量已经被锁定,那么此函数立即返回一个‘busy’的错误码,这个函数在优先级反转的情况下用来防止死锁是很有用的。
如果拥有锁的线程调用pthread_mutex_unlock()函数,那么将会解锁该互斥量;如果其它线程将要为处理被保护的数据请求互斥量,那么拥有该互斥量的线程在完成数据操作后调用该函数。发生下列情况,会有错误码返回:
如果互斥量已经被解锁;
如果互斥量被另一个线程拥有。
关于互斥量已经再也没有任何神奇的功用了……事实上,它们很类似于所有参与的线程之间的一个“君子协定”。
案例分析
运行结果
指针和内存的图像化
主程序申请了两块内存,各分为四块,上图标明了各个指针的指向,程序共创建四个线程,把两块4*100的内存区域分成四块,做连加运算得到mysum,之后再把所有的运算结果加起来赋值于dostr.sum,由于它是多线程共享的全局变量这里得利用互斥变量排队做加法,才能保证该值结果的正常。
<!--[endif]-->
<!--[if !vml]-->
<!--[endif]-->
Mutex(互斥量)是“mutual exclusion”的缩写,互斥量最主要的用途是在多线程中对共享数据同进行写操作时同步线程并保护数据。
互斥量在保护共享数据资源时可以把它想象成一把锁,在Pthreads库中互斥量最基本的设计思想是在任一时间只有一个线程可以锁定(或拥有)互斥量,因此,即使许多线程尝试去锁定一个互斥量时成功的只会有一个,只有在拥有互斥量的线程开锁后其它的线程才能锁定,就是说,线程必须排队访问被保护的数据。
互斥量常被用来防止竞争条件(race conditions),下面是一个涉及银行业务的竞争条件案例:
Thread 1 | Thread 2 | Balance |
---|---|---|
Read balance: $1000 | $1000 | |
Read balance: $1000 | $1000 | |
Deposit $200 | $1000 | |
Deposit $200 | $1000 | |
Update balance $1000+$200 | $1200 | |
Update balance $1000+$200 | $1200 |
拥有互斥量的线程常常做的一个事情就是更改全局变量值,这是一个安全方法,确保在多个线程更改同一个变量时,它最终的值与唯一一个线程执行更改操作后的结果是一致的,这个被更改的变量属于一个临界区(critical section)。
使用互斥量的一个标准的过程是:
创建并初始化互斥量;
多个线程试图锁定此互斥量;
有且只有一个线程成功的拥有了这个互斥量;
拥有互斥量的线程执行了一系列的操作;
拥有互斥量的线程解锁互斥量;
另一个线程获得此互斥量,并重复上面的过程;
最终互斥量被销毁。
当许多线程竞争一个互斥量时,在请求时失败的线程会阻塞——无阻塞的请求是用“trylock”而不是用“lock”,所以pthread_mutex_trylock()与pthread_mutex_lock()的区别就是在互斥量还没有解锁的情况下,前者不会阻塞线程。
在保护共享数据时,程序员的责任是确定每个线程需要用到互斥量,例如,如果有4个线程正在更改同一个数据,但是只有一个线程使用了互斥量,那么这个数据仍然会损坏。
创建并销毁互斥量
函数:
pthread_mutex_init (mutex,attr)
pthread_mutex_destroy (mutex)
pthread_mutexattr_init (attr)
pthread_mutexattr_destroy (attr)
用法:
互斥量必须要声明为pthread_mutex_t类型,并且在使用之前必须要被初始化。有两种方法初始化互斥量:
静态初始化,例如:pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;
动态初始化,使用pthread_mutex_init()过程,此函数可以设置互斥量属性对象attr;
注意,互斥量初始状态是未被锁定的(unlocked)。
对象attr常被用来设置互斥量对象的属性值的,而且必须是pthread_mutexattr_t类型(默认值是NULL)。Pthreads标准定义了3个互斥量可设置选项:
Protocol:为互斥量指定用来防止优先级倒置的规则的;
Prioceiling:为互斥量指定优先级上限的;
Process-shared:为互斥量指定进程共享的。
注意,不是所有的实现都要提供这三个可选的互斥量属性的。
pthread_mutexattr_init()和pthread_mutexattr_destroy()函数分别是用来创建和销毁互斥量属性的。
pthread_mutex_destroy()在互斥量不再被需要时,用来释放互斥量对象。
锁定和解锁互斥量
函数:
pthread_mutex_lock (mutex) pthread_mutex_trylock (mutex) pthread_mutex_unlock (mutex) |
线程用pthread_mutex_lock()函数通过指定的互斥量获得一个锁,如果互斥量已经被另一个线程锁定,那么这个请求会阻塞申请的线程,直到互斥量解锁。
pthread_mutex_trylock()尝试锁定互斥量,然而,如果互斥量已经被锁定,那么此函数立即返回一个‘busy’的错误码,这个函数在优先级反转的情况下用来防止死锁是很有用的。
如果拥有锁的线程调用pthread_mutex_unlock()函数,那么将会解锁该互斥量;如果其它线程将要为处理被保护的数据请求互斥量,那么拥有该互斥量的线程在完成数据操作后调用该函数。发生下列情况,会有错误码返回:
如果互斥量已经被解锁;
如果互斥量被另一个线程拥有。
关于互斥量已经再也没有任何神奇的功用了……事实上,它们很类似于所有参与的线程之间的一个“君子协定”。
案例分析
运行结果
# Pthreads i=0 Thread0: mysum=100.000000,dotstr.sum=100.000000 i=1 Thread1: mysum=100.000000,dotstr.sum=200.000000 i=2 Thread2: mysum=100.000000,dotstr.sum=300.000000 i=3 Thread3: mysum=100.000000,dotstr.sum=400.000000 Sum = 400.000000
指针和内存的图像化
主程序申请了两块内存,各分为四块,上图标明了各个指针的指向,程序共创建四个线程,把两块4*100的内存区域分成四块,做连加运算得到mysum,之后再把所有的运算结果加起来赋值于dostr.sum,由于它是多线程共享的全局变量这里得利用互斥变量排队做加法,才能保证该值结果的正常。
<!--[endif]-->
<!--[if !vml]-->
相关文章推荐
- POSIX线程的创建与取消—pthreads线程库实例笔记1
- POSIX线程库条件变量的使用——Pthreads线程库实例笔记4
- POSIX线程的连接和分离—pthreads线程库实例笔记2
- POSIX线程的创建与取消—pthreads线程库实例笔记1
- POSIX线程库条件变量的使用——Pthreads线程库实例笔记4
- 转:POSIX线程的创建与取消—pthreads线程库实例笔记1
- Unix学习笔记-----编程练习实例------使用vfork&&execv()在程序中加载可执行程序
- 日志收集系统Flume调研笔记第2篇 - Flume配置及使用实例
- 王保明老师Linux学习笔记---------信号----signal()函数使用实例
- c++学习笔记-map的使用实例(单词转换)
- j2me学习笔记【8】——TextField的使用实例
- j2me学习笔记【15】——使用低层用户界面显示文本小实例
- Python学习笔记(十)使用类和实例
- libevent源码笔记(二) 使用方法和实例
- (学习笔记)简单正则表达式的使用实例[javascript]
- 互斥量使用实例
- 基础学习笔记之opencv(18):kmeans函数使用实例
- POSIX线程互斥量的使用
- j2me学习笔记【9】——List中复选框的使用实例
- j2me学习笔记【12】——游戏操作Canvas类的up、down、left、right、fire属性使用实例