首页 > 编程知识 正文

Android线程,android创建子线程

时间:2023-05-04 00:28:26 阅读:148892 作者:3690

1 .引言:

互斥是一种常用的信号量,用于阻止两个进程或线程同时访问同一共享资源。 可以保证以下三点。

原子:将互斥量锁定为原子操作。 这意味着,如果一个线程锁定了独占量,操作系统(或pthread函数库)将确保其他线程可以同时锁定该独占量。

唯一性:如果某个线程锁定了独占量,则在解除锁定之前,没有其他线程可以锁定该独占量。

不忙等待:如果一个线程尝试锁定独占量,而第二个线程尝试锁定独占量,第二个线程将挂起。 不消耗cpu资源。 第二个线程将唤醒并继续执行,直到第一个线程释放独占量的锁定,然后锁定独占量。

从以上3点可以看出,通过互斥量可以保证对变量(重要代码段)的互斥访问。

2 .函数说明:

所需头文件: pthread.h1 )初始化互斥

函数原型: int pthread _ mutex _ init (pthread _ mutex _ t * MP,const pthread_mutexattr_t *mattr ) ) ) ) ) )

参数说明: mp互斥锁地址mattr属性通常为缺省null

在初始化互斥锁之前,必须将其内存清零。

如果互斥已初始化,则会解除锁定。 互斥锁可以位于进程之间共享的内存中,也可以位于进程的专用内存中。

2 )锁互斥锁

函数原型:

int pthread _ mutex _ lock (pthread _ mutex _ t * mutex ); #include pthread_mutex_t mutex; 输入返回; ret=pthread_mutex_lock(MP; /* acquire the mutex */

函数说明:

pthread_mutex_lock ) )返回时,互斥已被锁定。 调用线程是互斥锁的所有者。 如果互斥已被另一个线程锁定并拥有,则在启用互斥之前,调用线程将被阻止。

如果互斥类型为PTHREAD_MUTEX_NORMAL,则不提供死锁检测。 尝试重新锁定互斥会导致死锁。 如果线程尝试解锁的互斥锁没有被线程锁定或锁定,则会发生不确定的行为。

如果互斥锁定类型为PTHREAD_MUTEX_ERRORCHECK,将进行错误检查。 如果某个线程尝试重新锁定的互斥已被该线程锁定,则会返回错误。 如果线程尝试解锁的互斥未被线程锁定或锁定,则会返回错误。

如果互斥锁类型为PTHREAD_MUTEX_RECURSIVE,则互斥锁保留锁定计数的概念。 当线程首次成功获取互斥时,锁定计数将设置为1。 每当线程重新锁定互斥锁时,锁的数量就会增加1。 每当线程释放独占锁时,锁的数量就会减少1。 当锁数达到0时,此独占锁将可供其他线程获取。 如果线程尝试解锁的互斥未被线程锁定或锁定,则会返回错误。

如果互斥锁类型为PTHREAD_MUTEX_DEFAULT,则递归锁定互斥的尝试将导致不确定的行为。 对于未被调用线程锁定的互斥,尝试解除锁定会导致不确定的行为。 尝试解除未锁定的互斥锁会导致不确定的行为。

返回值:

pthread_mutex_lock ) )成功完成后返回零。 其他返回值表示发生了错误。 在以下情况之一下,函数将失败并返回相应的值:

EAGAIN :无法获取此互斥锁,因为它已超过互斥锁的最大递归锁次数。

EDEADLK :当前线程具有互斥锁。

3 )解锁排他锁

函数原型:

int pthread _ mutex _ unlock (pthread _ mutex _ t * mutex ); #include pthread_mutex_t mutex; 输入返回; ret=pthread_mutex_unlock(mutex; /* release the mutex */

函数说明: pthread_mutex_unlock )释放mutex引用的互斥对象。 互斥锁的释放方式取决于互斥锁的类型属性。 如果在调用pthread_mutex_unlock ()时多个线程被mutex对象阻止,则启用独占锁时的调度策略将确定获取独占锁的线程。 对于PTHREAD_MUTEX_RECURSIVE类型的排他锁,在计数达到零且调用线程不再锁定排他锁时可用。

返回值: pthread_mutex_unlock )成功完成后返回零。

其他返回值表示发生了错误。 在以下情况下,函数将失败并返回相应的值:

EPERM :的当前线程没有互斥锁。

4 )使用无阻塞互斥

函数原型:

int pthread _ mutex _ trylock (pthread _ mutex _ t * mutex ); #include pthread_mutex_t mutex; 输入返回; ret=pthread_mutex_tryloc

k(&mutex); /* try to lock the mutex */

函数说明:pthread_mutex_trylock()是pthread_mutex_lock()的非阻塞版本。如果mutex所引用的互斥对象当前被任何线程(包括当前线程)锁定,则将立即返回该调用。否则,该互斥锁将处于锁定状态,调用线程是其属主。

返回值:pthread_mutex_trylock()在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EBUSY :

由于mutex所指向的互斥锁已锁定,因此无法获取该互斥锁。

EAGAIN:描述:

由于已超出了mutex的递归锁定最大次数,因此无法获取该互斥锁。

5)销毁互斥锁

函数原型:

int pthread_mutex_destroy(pthread_mutex_t *mp); #include pthread_mutex_t mp; int ret; ret = pthread_mutex_destroy(&mp); /* mutex is destroyed */请注意,没有释放用来存储互斥锁的空间。

返回值:

pthread_mutex_destroy()在成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下任一情况,该函数将失败并返回对应的值。

EINVAL: mp指定的值不会引用已初始化的互斥锁对象。

3.例子:

互斥锁用来保证一段时间内只有一个线程在执行一段代码。必要性显而易见:假设各个线程向同一个文件顺序写入数据,最后得到的结果一定是灾难性的。

我们先看下面一段代码。这是一个读/写程序,它们公用一个缓冲区,并且我们假定一个缓冲区只能保存一条信息。即缓冲区只有两个状态:有信息或没有信息。

void reader_function ( void );

void writer_function ( void );

char buffer;

int buffer_has_item=0;

pthread_mutex_t mutex;

struct timespec delay;

void main ( void ){

pthread_t reader;

/*定义延迟时间*/

delay.tv_sec = 2;

delay.tv_nec = 0;

/*用默认属性初始化一个互斥锁对象*/

pthread_mutex_init (&mutex,NULL);

pthread_create(&reader, pthread_attr_default, (void *)&reader_function), NULL);

writer_function( );

}

void writer_function (void){

while(1){

/*锁定互斥锁*/

pthread_mutex_lock (&mutex);

if (buffer_has_item==0){

buffer=make_new_item( );

buffer_has_item=1;

}

/*打开互斥锁*/

pthread_mutex_unlock(&mutex);

pthread_delay_np(&delay);

}

}

void reader_function(void){

while(1){

pthread_mutex_lock(&mutex);

if(buffer_has_item==1){

consume_item(buffer);

buffer_has_item=0;

}

pthread_mutex_unlock(&mutex);

pthread_delay_np(&delay);

}

}

程序说明:

这里声明了互斥锁变量mutex,结构pthread_mutex_t为不公开的数据类型,其中包含一个系统分配的属性对象。函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如果需要声明特定属性的互斥锁,须调用函数pthread_mutexattr_init。函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来设置互斥锁属性。前一个函数设置属性pshared,它有两个取值,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进程中的线程同步,后者用于同步本进程的不同线程。

在上面的例子中,我们使用的是默认属性PTHREAD_PROCESS_ PRIVATE。后者用来设置互斥锁类型,可选的类型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它们分别定义了不同的上锁、解锁机制,一般情况下,选用最后一个默认属性。

pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直至调用pthread_mutex_unlock为止,均被上锁,即同一时间只能被一个线程调用执行。当一个线程执行到pthread_mutex_lock处时,如果该锁此时被另一个线程使用,那此线程被阻塞,即程序将等待到另一个线程释放此互斥锁。在上面的例子中,我们使用了pthread_delay_np函数,让线程睡眠一段时间,就是为了防止一个线程始终占据此函数。

4.饥饿和死锁的情形

当一个互斥量已经被别的线程锁定后,另一个线程调用pthread_mutex_lock()函数去锁定它时,会挂起自己的线程等待这个互斥量被解锁。可能出现以下两种情况:

“饥饿状态”:这个互斥量一直没有被解锁,等待锁定它的线程将一直被挂着,即它请求某个资源,但永远得不到它。用户必须在程序中努力避免这种“饥饿”状态出现。Pthread函数库不会自动处理这种情况。

“死锁”:一组线程中的所有线程都在等待被同组中另外一些线程占用的资源,这时,所有线程都因等待互斥量而被挂起,它们中的任何一个都不可能恢复运行,程序无法继续运行下去。这时就产生了死锁。Pthread函数库可以跟踪这种情形,最后一个线程试图调用pthread_mutex_lock()时会失败,并返回类型为EDEADLK的错误。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。