线程之售票系统pthread_mutex,_lock,_unlock

本文通过模拟四个线程同时处理票务销售的过程,探讨了线程同步的问题,并介绍了如何使用互斥锁来解决资源竞争导致的数据不一致性问题。

先看一下这篇文章
https://blog.youkuaiyun.com/csdn_kou/article/details/81148268

四个人同时买票票,引出线程

#include "head.h"
int ticket = 100;
void * route(void *arg)
{
    char *id = (char *)arg;
    while(1)
    {
        if(ticket>0)
        {
            usleep(1000);
            printf("%s sells:%d\n",id,ticket);
            ticket--;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    key_t key = ftok (".",1);

    pthread_t t1,t2,t3,t4;
    pthread_create(&t1,NULL,route,"thread 1");
    pthread_create(&t2,NULL,route,"thread 2");
    pthread_create(&t3,NULL,route,"thread 3");
    pthread_create(&t4,NULL,route,"thread 4");

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

    return 0;
}

这里写图片描述
四个人抢票,争的票都卖出负数了,这在实际中是不可以的

改进:引入互斥量加锁和解锁概念

#include "head.h"
#include <pthread.h>
#include <unistd.h>

int ticket = 100;
pthread_mutex_t mutex;

void * route(void *arg)
{
    char *id = (char *)arg;

    while(1)
    {
        pthread_mutex_lock(&mutex);
        if(ticket>0)
        {
            usleep(1000);
            printf("%s sells:%d\n",id,ticket);
            ticket--;
            pthread_mutex_unlock(&mutex);
        }
        else
        {
            break;
        }
    }

}

int main()
{
    key_t key = ftok (".",1);

    pthread_t t1,t2,t3,t4;
    pthread_create(&t1,NULL,route,"thread 1");
    pthread_create(&t2,NULL,route,"thread 2");
    pthread_create(&t3,NULL,route,"thread 3");
    pthread_create(&t4,NULL,route,"thread 4");

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

    return 0;
}

这里写图片描述
这是我们发现票是卖的刚刚好,可是卡在那里了。

因为卖完最后一张票,没有进入if语句,在else语句中没有解锁,特别注意的是,用一次
pthread_mutex_lock(&mutex);
就必须在任何有可能退出的地方进行解锁
pthread_mutex_unlock(&mutex);
改进之后就刚刚好
这里写图片描述

1. 实验目的和要求 1. 理解线程的概念 2. 掌握在Linux下创建线程的方法 3. 掌握基本的线程同步机制 2. 实验内容 1. 写一段C程序,创建一个线程(可以参考下面代码) 2. 写一段C程序,创建十个线程(可以参考下面代码) 3. 写一段C程序,模拟售票窗口。假设有100张车票(临界资源)和四个窗口(线程),每个线程在售 出一张票时输出“Window+窗口号(从1到4)+Sales+票号(从1到100)”。 3. 实验指导 1. POSIX线程(POSIX threads),简称Pthreads,是线程的POSIX标准。 该标准定义了创建和操纵 线程的一整套API。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操 作系统的线程。 2. 编译需要注意:在编译 pthread 程序时,你需要在编译命令中链接 pthread 库。在大多数情况下, 你需要使用 -pthread 编译选项来确保正确地链接 pthread 库以及设置必要的编译标志。这会告 诉编译器和链接器将 pthread 相关的库链接到你的程序中。 例如,使用 gcc 编译时,你可以这样做: gcc your_program.c -o your_program -pthread 3. 创建线程: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine) (void *), void *arg); 参数: thread :一个指向 使用默认属性。 pthread_t 类型的指针,用于存储新线程的标识符。 attr :一个指向 pthread_attr_t 类型的指针,表示新线程的属性。通常可以传入 NULL , start_routine :一个指向函数的指针,新线程将从这个函数开始执行。函数应该返回 void* 类型,接受一个 void* 参数。 arg :传递给 start_routine 函数的参数。 返回值:若成功,返回0;若出错,返回出错编号。 4. 阻塞等待: int pthread_join(pthread_t thread, void **retval); 参数: thread :要等待结束的线程的标识符 thread :要等待结束的线程的标识符。 retval :一个指向指针的指针,用于存储目标线程的返回值。 返回值:若成功,返回0;若出错,返回出错编号。 一般来讲主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程 执行完成之后再结束,这个时候就要用到 pthread_join() 方法。即 pthread_join() 的作用可以这样 理解:主线程等待子线程的终止。也就是在子线程调用了 pthread_join() 方法后面的代码,只有等到 子线程结束了才能执行。 4. 互斥锁: 1. 初始化互斥锁: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); 参数: mutex :指向要初始化的互斥锁对象的指针。 attr :指向一个互斥锁属性对象的指针,通常可以传入 NULL 来使用默认的属性。 返回值:函数返回值为 0 表示初始化成功,非零值表示初始化失败。 2. 加锁: int pthread_mutex_lock(pthread_mutex_t *mutex); 参数: mutex : 一个指向互斥锁对象( pthread_mutex_t 类型)的指针。 返回值:若函数调用成功,返回值为 0。若函数调用失败,返回值为错误代码。 3. 解锁: int pthread_mutex_unlock(pthread_mutex_t *mutex); 参数: mutex : 一个指向要释放的互斥锁对象( pthread_mutex_t 类型)的指针。 返回值:若函数调用成功,返回值为 0。若函数调用失败,返回值为错误代码。 4. 销毁互斥锁: int pthread_mutex_destroy(pthread_mutex_t *mutex); 参数: mutex : 一个指向互斥锁对象( pthread_mutex_t 类型)的指针。 返回值:若函数调用成功,返回值为 0。若函数调用失败,返回值为错误代码。 4. 参考代码 1. 第一个实验参考代码: #include <stdio.h> #include <pthread.h> 2. 第二个实验参考代码: void* run(void* arg) { printf("This is a thread.\n"); } int main() { pthread_t tid; pthread_create(&tid, NULL, run, NULL); pthread_join(tid, NULL); printf("Thread Ended.\n"); return 0; } #include <stdio.h> #include <pthread.h> #include <unistd.h> void* run(void* arg) { for (int i = 0; i < 5; i++) { printf("Hello in Thread (&d) \n", (int)arg); usleep(100); } } int main() { pthread_t tid[10]; for (int i = 0; i < 10; i++) { pthread_create(&tid[i], NULL, run, (void*)i); } for (int i = 0; i < 10; i++) { pthread_join(tid[i], NULL); } return 0 给我以下4点: 三、实验环境 (实验平台描述,操作系统、数据库管理系统、编译环境..) 四、实验过程描述 (语言描述实验细节+具体代码实现+截图) 五、结果分析 得到什么结果(数据)?有什么问题?分析原因 六、结论
06-21
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值