线程的互斥和同步_多线程处理问题的能力

线程的互斥和同步_多线程处理问题的能力并发的线程访问了相同的资源,所以造成了数据的不确定性

目录

前言

一、互斥锁是什么?

二、互斥锁的使用

 三、代码实现过程

1.初始化互斥锁

2.互斥锁上锁

3.互斥锁解锁

4.互斥锁释放

5.代码示例

四、死锁


前言

线程通信只需要操作共享的进程数据段即可,虽然很容易,但也有其弊端,正因为并发的线程访问了相同的资源,所以造成了数据的不确定性。因此,线程的通信需要结合一些同步互斥机制一起使用

假如没有一些同步互斥机制,一个线程在读一个全局变量时,刚好另外一个线程在写这个全局变量,就容易造成数据的混乱


一、互斥锁是什么?

互斥锁是用以保护对共享资源的操作,即保护线程对共享资源的操作代码可以完整执行,而不会在访问的中途被其他线程介入对共享资源访问。通常把对共享资源操作的代码段,称之为临界区,其共享资源也可以称为临界资源。于是这种机制——互斥锁的工作原理就是对临界区进行加锁,保证处于临界区的线程不被其他线程打断,确保其临界区运行完整

二、互斥锁的使用

1.使用之前需要先初始化一个互斥锁

2.如果线程加锁成功,则可以访问共享资源,期间不会被打断,在访问结束之后解锁

3.线程在进行上锁时,其锁资源被其他线程持有,那么该线程则会执行阻塞等待,等待锁资源被解除之后,才可以进行加锁

4.互斥锁并不能保证线程的执行先后,但却可以保证对共享资源操作的完整性

5.图示:

线程的互斥和同步_多线程处理问题的能力

 三、代码实现过程

互斥锁的使用包括初始化互斥锁互斥锁上锁互斥锁解锁互斥锁释放

1.初始化互斥锁

int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

参数:

mutex用来指定互斥锁额标识符,类似于ID,其类型为pthread_mutex_t

attr为互斥锁的属性,一般设置为NULL

2.互斥锁上锁

int pthread_mutex_lock(pthread_mutex_t *mutex);

3.互斥锁解锁

int pthread_mutex_unlock(pthread_mutex_t *mutex);

4.互斥锁释放

pthread_mutex_destroy(pthread_mutex_t *mutex)

5.代码示例

此示例创建了五个线程,给五个线程的执行函数一样,给执行函数加锁,保证了每个线程执行程序的完整性

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define NUM_THREADS 5
pthread_mutex_t lock1,lock2; 
int k;
void *PrintHello(void *tt)/* 线程函数 */
{
    long tid;
    int i,j;
    tid = (long)tt;
    while(1)
    {   sleep(2);
        pthread_mutex_lock(&lock1);//上锁1
        printf("It's thread #%ld begining!\n", tid);/* 打印线程对应的参数 */
    //sleep(5);
/*         for(i=0;i<55555;i++)
            for(j=0;j<9999;j++);//消耗cpu,延时 */
        pthread_mutex_lock(&lock2);//上锁2
        for (k = 0; k < 5; k++) 
        { 
            printf("thread #%ld Job %d printing \n", tid,k); 
            for(i=0;i<100000;i++)
            for(j=0;j<6666;j++);
        }   
        printf(" thread #%ld is over!\n", tid); 
        pthread_mutex_unlock(&lock2);//一个线程中操作多个互斥锁时,加锁与解锁的顺序一定是相反的
        pthread_mutex_unlock(&lock1);//解锁1
        /* 线程先加锁1,后加锁2,之后一定要先解锁2,再解锁1 */
        
    }
}

int main (int argc, char *argv[])
{
    pthread_t threads[NUM_THREADS];
    long t;
    for(t=0; t<NUM_THREADS; t++)
    {   
        /* 循环创建 5 个线程 */
        printf("In main: creating thread %ld\n", t);
        pthread_create(&threads[t], NULL, PrintHello, (void *)t); /* 创建线程,系统自动分配资源 */
    } 
    pthread_mutex_init(&lock1,NULL);//初始化互斥锁
    pthread_mutex_init(&lock2,NULL);//初始化互斥锁
    while(1);
}

注意:

一个线程中操作多个互斥锁时,加锁与解锁的顺序一定是相反的,否则也会导致错误。例如上述示例,如果线程先加锁1,后加锁2,之后一定要先解锁2,再解锁1

四、死锁

多个线程对多个互斥锁交叉使用,每一个线程都试图对其他线程所持有的互斥锁进行加锁。如图所示的情况,线程分别持有了对方需要的锁资源,并相互影响,可能会导致程序无限阻塞,就会造成死锁

线程的互斥和同步_多线程处理问题的能力

今天的文章线程的互斥和同步_多线程处理问题的能力分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/75242.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注