Linux C 多线程编写-----例子:10个售票窗口协作卖掉150张票

这个是比较简单的例子,有助于初学多线程的人理解多线程的工作模式,后期会不断的跟进多线程的进阶应用等。

储备知识:

1.多线程是一种多任务并发的工作方式,在linux中线程包括内核线程和用户线程,内核线程有内核管理,不需要我们做更多的工作,我们这里将的是用户线程,线程统一由用户线程来切换。

2.线程相关函数:

int pthread_create(pthread_t id,pthread_attr_t *attr, void *(*start_runtine)(void *), void *arg);//线程创建函数

获取线程ID(即上面创建的pthread_t id):pthread_t pthread_self();

退出线程:void pthread_exit(void *retval);

挂起线程:int pthread_join(pthread_t id,void **return);

线程同步:在POSIX中提供线程同步的方式有两种,条件变量和互斥锁

互斥锁:

pthread_mutex_t *mutex;//互斥锁变量

int pthread_mutex_init(pthread_mutex_t *mutex, pthread_attr_t *attr);//初始化一个互斥锁

int pthread_mutex_lock(pthread_mutex_t *mutex);//锁定互斥锁,这样子当一个线程锁定的话,另一个线程就会处于等待状态

int pthread_mutex_unlock(pthread_mutex_t  *mutex);//解锁互斥锁,如果解锁后,处于等待状态的线程就有机会访问临界区

条件变量:其实是对互斥锁的一种补充,因为线程可以在等待条件变量的时候同时解锁,这在生产者和消费者模式可以体现。

pthread_cond_t cond;

int pthread_cond_init(pthread_cond_t *cond, const pthread_cond_addr *attr);//初始化一个条件变量,后面参数attr是条件变量的属性

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);//释放互斥量mutex,等待条件变量cond

int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex,const struct timespec *abstime);//释放互斥量mutex,等待条件变量cond,与pthread_cond_wait函数不一样的是,该函数可以是线程在abstime时间内不阻塞。

int pthread_cond_signal(pthread_cond_t *cond);//释放条件变量

int pthread_cond_broadcast(pthread_cond_t *cond);//释放所有由cond阻塞的线程,这里要小心使用

3.线程属性,这些属性在使用前,必须调用相关的初始化函数pthread_xxx_init(xxx *);

线程属性:pthread_attr_t 

typedef struct
{
       int                               detachstate;   线程的分离状态,这个跟pthread_join相关,如果一个线程调用join获取另一个线程的状态的时候,就需要用到这个属性。
       int                               schedpolicy;  线程调度策略
       struct sched_param              schedparam;  线程的调度参数
       int                               inheritsched;  线程的继承性
       int                                scope;       线程的作用域
       size_t                           guardsize;   线程栈末尾的警戒缓冲区大小
       int                                stackaddr_set;
       void *                          stackaddr;   线程栈的位置
       size_t                           stacksize;    线程栈的大小
}pthread_attr_t;
上面的相关属性,POSIX大部分都提供了相应的接口来操作。如设置调度测略:int pthread_attr_setschedpolicy(pthread_attr_t  *attr, int policy);等

int pthread_attr_init(pthread_attr_t  *attr);//初始化线程属性对象

int pthread_attr_destroy(pthread_attr_t  *attr);//销毁线程属性对象

。。。。。

例子:10个窗口协作卖掉150张票

下面是正常情况下,150张票依次由窗口0~9号卖完,即0号卖完10张票,接下来1号继续卖完十张票。。。这种是常规的处理方法,代码实现如下:

#define NUMOFTICKET 150
#define NUMAGENT 10
void sellTickets(int agent, int task);
int main()
{
    int i;
    for(i = 0; i < NUMAGENT; i++)
    {
        sellTickets(i,NUMOFTICKET/NUMAGENT);
    }
    return 0;
}
void sellTickets(int agent, int task)
{
    assert(agent >= 0);
    while(task > 0)
    {
        printf("agent %d sell one ticket!\n",agent);
        task--;
    }
    printf("agent %d sell all ticket!\n",agent);
}
但是这种方式比较不符合现代的服务方式,现在一般都是0~9号窗口同时卖票,哪个窗口有空闲时间,有多余的票数就可以提供服务,这种用多线程的方法就可以实现这种方法:

static int numofticket = 150;
const int numofagent = 10;
pthread_mutex_t mutex;
void* sellTicket(void* agent);
int main()
{
    int i;
    int fail = -1;
    pthread_t npid[numofagent]
    for(i = 0;i<numofagent; i++)
    {
        fail = -1;
        fail = pthread_create(&npid[i],NULL, sellTicket,(int *)i);//创建10个线程,10个线程调用sellTicket函数
        if(!fail)
        {
            printf("Create thread %d success!\n",i);
        }
        else
        {
            printf("Create Thread failed!\n");
        }
    }
    while(1);
    printf("Back to main!\n");
    return 0;
}
void* sellTicket(void* agent)
{
    while(numofticket > 0)
    {
      printf("agent %d sell a ticket!\n",(int)agent);
        pthread_mutex_lock(&mutex);//互斥锁,表示下面是一个临界区
        numofticket--;
        pthread_mutex_unlock(&mutex);
        sleep(2);
    }
    printf("Sell all ticket!\n");
    return NULL;
}

上面的程序设计是依次创建十个线程,然后十个线程针对资源numofticket 交替出售,谁有空闲谁就占有CPU买票,因为numofticket是一个临界区(多个线程访问的互斥区),所以上面通过互斥锁mutex控制临界区的访问,这里创建线程从0~9号,线程创建完成后就可能开始运行,并且随机的,所以可能打出的结果如下:

Create thread 1 success!
Create thread 2 success!
Create thread 3 success!
Create thread 4 success!
Create thread 5 success!
Create thread 6 success!
Create thread 7 success!
Create thread 8 success!
Create thread 9 success!
agent 3 sell a ticket!
agent 4 sell a ticket!
agent 5 sell a ticket!
agent 6 sell a ticket!
agent 7 sell a ticket!
。。。。。这里没有全部打出贴上,抱歉,篇幅太多

根据以上线程的介绍,用多线程实现的例子有:生产者和消费者等


    



  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值