线程同步互斥机制--互斥锁

目录

前言

一、互斥锁是什么?

二、互斥锁的使用

 三、代码实现过程

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

四、死锁

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

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香菜是个好东西

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值