当前位置:Linux教程 - Linux - Solaris多线程编程(4)

Solaris多线程编程(4)



         4 在程序中使用同步对象这一章描述了线程同步的类型,并描述了什么时候使用同步机制以及如何使用同步机制。l 互斥锁的属性l 使用互斥锁l 条件变量的属性l 使用条件变量l 信号量l 读写锁的属性l 使用读写锁l 跨进程的同步l 不需线程库支持的进程间锁定l 各种原语的比较同步对象其实和程序中访问的数据一样是内存中的变量。尽管在不同进程中的线程一般是互不可见的(即一个线程不能访问其他进程中线程的资源),但不同进程中的线程可以通过同步对象互相通讯,这些同步对象被放在由线程控制的共享内存中。同步对象也可以被放在文件里,这样它们的生存周期可以超过创建它们的进程。当前有这样几种同步对象可供使用:l 互斥锁l 条件变量l 信号量在下列情况中,使用同步机制会带来好处:l 只有用同步机制才能保证共享数据的一致性时。l 当不同进程中的线程共用一个同步对象时。注意,同步对象只能由一个进程初始化,对一个同步对象进行重复初始化会使它变成非锁定状态。l 当同步可以保证可变数据的安全性时。如果一个进程映射了一个文件,而且锁定了这个文件的某个记录,那么如果其他映射了这个文件的进程要锁定这个锁,都将被阻塞,直到这个锁被前一个进程释放。l 即使是访问一个基本类型的变量(如整数),有时候也需要同步机制。例如在整数宽度和数据总线宽度不一致时,对一个整数类型变量的访问可能需要几个内存访问周期,或几个机器指令,这时如果多个线程都需要访问共享整数类型变量,那么应该使用同步机制。尽管在SPARC体系结构下不会发生上述情况,但作为可移植的程序最好使用同步机制。注意:在32位体系结构下,一个long 型变量不是原子类型,对一个long型变量的访问被分解成对两个32位数的访问,所以对一个long型变量的访问可能被其他线程打断。而数据类型int, char, float和指针在SPARC和x86计算机中都是原子类型。对这种类型变量的访问不会被其他线程打断。互斥锁的属性用互斥锁可以使线程顺序运行。互斥锁通常被用来保证一段时间内只有一个线程在执行一段关键的代码。即互斥锁可以保证:在一段时间内,某段代码只被一个线程调用。为了改变缺省的互斥锁属性,你可以声明并初始化一个属性对象。经常的,互斥锁属性对象在程序开始时被设置,以便对它们进行修改。下面的表列出了对互斥锁属性进行操作的函数。表4-1 访问互斥锁属性的函数初始化一个互斥锁属性对象pthread_mutexattr_init(3T)释放一个互斥锁属性对象pthread_mutexattr_destroy(3T)置互斥锁的作用域pthread_mutexattr_setpshared(3T)取互斥锁的作用域pthread_mutexattr_getpshared(3T)置互斥锁的类型属性pthread_mutexattr_settype(3T)取互斥锁的类型属性pthread_mutexattr_gettype(3T)定义互斥锁的作用域时,Solaris和POSIX之间有区别,如下表。表4-2 互斥锁作用域比较SolarisPOSIXDefinitionUSYNC_PROCESSPTHREAD_PROCESS_SHARED用来与其他进程中的线程同步USYNC_PROCESS_ROBUST没有相应的POSIX常量用来“鲁棒”的同步不同进程中的线程USYNC_THREADPTHREAD_PROCESS_PRIVATE用来同步本进程中的不同线程初始化一个互斥锁属性对象pthread_mutexattr_init(3T)pthread_mutexattr_init(3T)被用来将属性对象的值初始化为缺省值。并分配属性对象占用的内存空间。属性对象中pshared属性的缺省值是PTHREAD_PROCESS_PRIVATE。这表示由这个属性对象创建的互斥锁只能在进程内使用。函数原型:int pthread_mutexattr_init( pthread_mutexattr_t *mattr );#include pthread_mutexattr_t mattr;int ret;/* initialize an attribute to default value */ret = pthread_mutexattr_init( &mattr );mattr为pthread_mutexattr_t类型,这是不公开的数据类型,其中包含一个系统分配的属性对象。mattr中pshared属性表示用这个属性对象创建的互斥锁的作用域,它的取值可以是PTHREAD_PROCESS_PRIVATE(缺省值)或PTHREAD_PROCESS_SHARED。如果需要重新初始化一个互斥锁属性对象,必须先用pthread_mutexattr_destroy(3T)函数将它释放掉。因为用来初始化互斥锁属性对象的pthread_mutexattr_init()函数会为这个对象重新分配内存,如果不释放互斥锁属性对象就重新初始化这个对象会造成内存泄露。返回值pthread_mutexattr_init()函数成功后,返回一个0。任何其他返回值都表示有错误发生。当如下情况发生时,pthread_mutexattr_init()函数失败并返回相应的错误代码。ENOMEM 没有足够的内存初始化互斥锁属性对象。释放一个互斥锁属性对象pthread_mutexattr_destroy(3T)pthread_mutexattr_destroy(3T)释放互斥锁属性对象占用的内存(这些内存是由pthread_mutexattr_init()函数分配的)。函数原型:int pthread_mutexattr_destroy( pthread_mutexattr_t *mattr );#include pthread_mutexattr_t mattr;int ret;/* destroy an attribute */ret = pthread_mutexattr_destroy( &mattr );返回值pthread_mutexattr_destroy()函数成功后,返回一个0。任何其他返回值都表示有错误发生。当如下情况发生时,pthread_mutexattr_destroy()函数失败并返回相应的错误代码。EINVAL mattr的值非法。设置作用域属性pthread_mutexattr_setpshared(3T)pthread_mutexattr_setpshared(3T)函数设置互斥锁的域。互斥锁的域可以是进程内的也可以是进程间的。如果互斥锁属性对象的pshared属性被置为PTHREAD_PROCESS_SHARED。那么由这个属性对象创建的互斥锁将被保存在共享内存中,可以被多个进程中的线程共享。这等价于Solaris线程中的USYNC_PROCESS常量。函数原型:int pthread_mutexattr_setpshared( pthread_mutexattr_t *mattr, int pshared );#include pthread_mutexattr_t mattr;int ret;ret = pthread_mutexattr_init( &mattr );/* resetting to its default value: private */ret = pthread_mutexattr_setpshared( &mattr, PTHREAD_PROCESS_PRIVATE );如果pshared属性被置为PTHREAD_PROCESS_PRIVATE,那么只有和创建这个互斥锁的线程在同一个进程中的线程才能访问这个互斥锁。返回值pthread_mutexattr_setpshared()函数成功后,返回一个0。任何其他返回值都表示有错误发生。当如下情况发生时,pthread_mutexattr_setpshared()函数失败并返回相应的错误代码。EINVAL mattr的值非法。取作用域属性pthread_mutexattr_getpshared(3T)pthread_mutexattr_getpshared(3T)函数返回属性对象的互斥锁作用域属性。函数原型:int pthread_mutexattr_getpshared( pthread_mutexattr_t *mattr, int *pshared );#include pthread_mutexattr_t mattr;int pshared, ret;/* get pshared of mutex */ret = pthread_mutexattr_getpshared( &mattr, &pshared );用pthread_mutexattr_getpshared()函数取得的属性对象的pshared属性值可以是以下值:PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE。返回值pthread_mutexattr_getpshared()函数成功后,返回一个0。任何其他返回值都表示有错误发生。当如下情况发生时,pthread_mutexattr_getpshared()函数失败并返回相应的错误代码。EINVAL mattr的值非法。设置互斥锁类型属性pthread_mutexattr_settype(3T)#include int pthread_mutexattr_settype( pthread_mutexattr_t *attr, int type );pthread_mutexattr_settype(3T)函数设置互斥锁类型属性。缺省的互斥锁类型属性是PTHREAD_MUTEX_DEFAULT。函数中type参数指定互斥锁类型属性。合法的类型属性值有:PTHREAD_MUTEX_NORMAL这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起这个线程的死锁。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。PTHREAD_MUTEX_ERRORCHECK这种类型的互斥锁会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会返回一个错误代码。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。PTHREAD_MUTEX_RECURSIVE如果一个线程对这种类型的互斥锁重复上锁,不会引起死锁,一个线程对这类互斥锁的多次重复上锁必须由这个线程来重复相同数量的解锁,这样才能解开这个互斥锁,别的线程才能得到这个互斥锁。如果试图解锁一个由别的线程锁定的互斥锁将会返回一个错误代码。如果一个线程试图解锁已经被解锁的互斥锁也将会返回一个错误代码。这种类型的互斥锁只能是进程私有的(作用域属性为PTHREAD_PROCESS_PRIVATE)。PTHREAD_MUTEX_DEFAULT这种类型的互斥锁不会自动检测死锁。如果一个线程试图对一个互斥锁重复锁定,将会引起不可预料的结果。如果试图解锁一个由别的线程锁定的互斥锁会引发不可预料的结果。如果一个线程试图解锁已经被解锁的互斥锁也会引发不可预料的结果。POSIX标准规定,对于某一具体的实现,可以把这种类型的互斥锁定义为其他类型的互斥锁。(对Solaris系统来说,PTHREAD_PROCESS_DEFAULT类型的互斥锁被定义为PTHREAD_PROCESS_NORMAL类型的互斥锁)返回值pthread_mutexattr_settype()函数成功后,返回一个0。任何其他返回值都表示有错误发生。当如下情况发生时,pthread_mutexattr_settype()函数失败并返回相应的错误代码。EINVAL type的值非法或attr的值非法。获取互斥锁类型属性pthread_mutexattr_gettype(3T)#include int pthread_mutexattr_gettype( pthread_mutexattr_t *attr, int *type );pthread_mutexattr_gettype(3T)函数取互斥锁类型属性。缺省的互斥锁类型属性是PTHREAD_MUTEX_DEFAULT。返回的互斥锁类型属性可能是:PTHREAD_MUTEX_NORMALPTHREAD_MUTEX_ERRORCHECKPTHREAD_MUTEX_RECURSIVEPTHREAD_MUTEX_DEFAULT参见 “pthread_mutexattr_settype(3T)”对这几种类型的描述。使用互斥锁配置完一个互斥锁属性以后,就可以初始化互斥锁本身了。下列函数被用来操作互斥锁。表4-3 互斥锁操作函数初始化一个互斥锁pthread_mutex_init(3T)锁定一个互斥锁pthread_mutex_lock(3T)解锁一个互斥锁pthread_mutex_unlock(3T)非阻塞锁定互斥锁pthread_mutex_trylock(3T)释放一个互斥锁pthread_mutex_destroy(3T)在缺省的调度策略(SCHED_OTHER)下,如果有多个线程阻塞在一个互斥锁上,那么当这个互斥锁被解锁时,各线程被唤醒的顺序是不一定的。一般是按照线程的优先级高低来释放阻塞线程,重新锁定互斥锁。初始化一个互斥锁pthread_mutex_init(3T)
    发布人:gloomy 来自: