欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程-------线程的同步与互斥

程序员文章站 2022-05-05 10:29:50
...

一、什么是互斥量(mutex)
先来看一段代码:操作共享变量会有问题的售票系统

Makefile
多线程-------线程的同步与互斥
mypthread.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int ticket = 100;

void *sell_ticket(void *arg)
{
    char *id  = (char*)arg;
    while(1)
    {
        if(ticket > 0)
        {
            usleep(1000);
            printf("%s get ticket,id is %d\n",(char*)arg,ticket);
            ticket--;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    pthread_t t1,t2,t3,t4;
    pthread_create(&t1,NULL,sell_ticket, "thread 1 is runing");
    pthread_create(&t2,NULL,sell_ticket, "thread 2 is runing");
    pthread_create(&t3,NULL,sell_ticket, "thread 3 is runing");
    pthread_create(&t4,NULL,sell_ticket, "thread 4 is runing");

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_join(t3, NULL);
    pthread_join(t4, NULL);
    return 0;
}

运行之:
多线程-------线程的同步与互斥
线程不断买票,买到后面时出现-1,-2

-1 -2意味着什么 意味着票务系统出错了,(数据不一致问题:临界资源有可能在同一时间被多个线程访问,无法保证原子性)

  • 怎样解决:加锁:实现互斥(1、保证一个线程在访问临界资源的时候,其他线程不能访问;2、如果线程不在临界区中执行,那么该线程不能阻止其他线程进入临界区)

图示一下互斥量(加的锁:在临界区前后 加锁解锁)
多线程-------线程的同步与互斥
1、互斥量的相关接口
(1)初始化互斥量

* 方法一:静态分配
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
* 方法二:动态分配
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

//参数
  mutex:要初始化的互斥量
  attr:NULL

全局变量为什么能被线程看到:线程之间资源共享
(2)销毁互斥量

#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);

// 返回值
成功返回0;失败返回错误码

(3)互斥量加锁和解锁(加锁和解锁是原子的)

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex); 
int pthread_mutex_unlock(pthread_mutex_t *mutex);

// 返回值:成功返回0;失败返回错误码

调用pthread_mutex_lock时遇到的情况:

(1)互斥量处于未锁状态,该函数会将互斥量锁定,同时返回成功
(2)发起函数调用时,其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互斥量,辣么pthread_mutex_lock调用会陷入阻塞,等待互斥量解锁

改进一下刚开始的票务系统的代码:

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int ticket = 100;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

void *sell_ticket(void *arg)
{
    char *id  = (char*)arg;
    while(1)
    {
       // 给临界区加锁
        pthread_mutex_lock(&lock);
        if(ticket > 0)
        {
            usleep(1000);
            printf("%s get ticket,id is %d\n",(char*)arg,ticket);
            ticket--;
             pthread_mutex_unlock(&lock);
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
    }
}

int main()
{
     pthread_t t1,t2,t3,t4;
     pthread_create(&t1,NULL,sell_ticket, "thread 1 is runing");
     pthread_create(&t2,NULL,sell_ticket, "thread 2 is runing");
     pthread_create(&t3,NULL,sell_ticket, "thread 3 is runing");
     pthread_create(&t4,NULL,sell_ticket, "thread 4 is runing");

     pthread_join(t1, NULL);
     pthread_join(t2, NULL);
     pthread_join(t3, NULL);
     pthread_join(t4, NULL);

     // 销毁
     pthread_mutex_destroy(&lock);
     return 0;
 }

运行之:
多线程-------线程的同步与互斥