zoukankan      html  css  js  c++  java
  • 9、多线程小结(2)(转)

    9、多线程小结(2)

     

    3)合并线程:pthread_join

         int pthread_join(pthread_t* thread, void **ret);

         第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。关于什么是可joinable的线程,参见[3]。

    4)通过到斥实现线程同步

    1)声明互斥锁变量:pthread_mutext_t mutex; 
    pthread_mutex_t为不公开的数据类型,其中包含一个系统分配的属性对象。

    2)互斥锁初始化:pthread_mutex_init(pthread_mutex_t *mymutex, const pthread_mutexattr_t *attr );

        第一个参数接受一个指针以初始化为互斥对象,该指针指向一块已分配好的内存区。第二个参数,可以接受一个可选的pthread_mutexattr_t指针。这个结构可用来设置各种互斥对象属性。

    3)锁定互斥锁 :pthread_mutex_lock (&mutex);

    pthread_mutex_lock声明开始用互斥锁上锁,此后的代码直至调用pthread_mutex_unlock为止,均被上锁,同一时间只能被一个线程调用执行。

    4)打开互斥锁:pthread_mutex_unlock(&mutex);

    示例代码

    View Code
    复制代码
    #include <stdio.h>
    #include
    <pthread.h>
    #include
    <stdlib.h>
    #include
    <unistd.h>

    int allTickets=10; //假设总共还剩余十张票
    pthread_mutex_t mutex; //声明互斥锁

    void* window1(void* arg)
    {
    while(allTickets >=1)
    {
    pthread_mutex_lock(
    &mutex); //加锁
    if(allTickets >=1)
    {
    printf(
    "I am window1:%d\n",allTickets);
    allTickets
    --;
    }
    pthread_mutex_unlock(
    &mutex); //对共享资源的访问完后解锁
    sleep(1);
    }
    }
    void* window2(void* arg)
    {
    while(allTickets>=1)
    {
    pthread_mutex_lock(
    &mutex);
    if(allTickets>=1)
    {
    printf(
    "I am window2:%d\n",allTickets);
    allTickets
    --;
    }
    pthread_mutex_unlock(
    &mutex);
    sleep(
    2);
    }
    }

    int main(void)
    {
    pthread_t sell1,sell2;
    pthread_mutex_init (
    &mutex,NULL);
    pthread_create(
    &sell1, NULL, window1, NULL);
    pthread_create(
    &sell2, NULL, window2, NULL);
    pthread_join(sell1,NULL);
    pthread_join(sell2,NULL);
    return1;
    }
    复制代码

     

     

    5)其他

    互斥锁判断上锁:pthread_mutex_trylock()

    消除互斥锁:pthread_mutex_destroy()

    5)通过信号量实现线程同步

    1)基本概念

        信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用函数sem_post( )增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait( )减少信号量

        和信号量有关的一些函数,它们都在头文件 semaphore.h中定义。信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init( )用来初始化一个信号量。它的原型为:

        extern int sem_init _P ((sem_t *sem, int  pshared, unsigned int value));

        sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。

        函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不再阻塞,选择机制同样是由线程的调度策略决定的。

        函数sem_wait( sem_t *sem )被用来阻塞当前线程,直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。

        函数sem_destroy(sem_t *sem)用来释放信号量sem

    示例生产者与消费者

    View Code
    复制代码
    #include <stdio.h>
    #include
    <pthread.h>
    #include
    <semaphore.h>
    #include
    <stdlib.h>
    #include
    <unistd.h>

    #define N 20

    int k =0; //保存现有产品数量
    sem_t full;
    sem_t empty;
    pthread_mutex_t mutex;

    void* producer(void* arg)
    {
    while(1)
    {
    sem_wait(
    &empty);
    pthread_mutex_lock(
    &mutex);
    k
    ++;
    printf(
    " produce one Remaining:%d\n", k);
    pthread_mutex_unlock(
    &mutex);
    sem_post(
    &full);
    sleep(
    1);
    }
    }

    void* consumer(void* arg)
    {
    while(1)
    {
    sem_wait(
    &full);
    pthread_mutex_lock(
    &mutex);
    k
    --;
    printf(
    " consumer one the rest :%d\n",k);
    pthread_mutex_unlock(
    &mutex);
    sem_post(
    &empty);
    sleep(
    1);
    }
    }

    main()
    {
    pthread_t thread1, thread2, thread3;
    sem_init(
    &full,0,0);
    sem_init(
    &empty,0,N);

    pthread_create(
    &thread1, NULL, producer, NULL);
    pthread_create(
    &thread2, NULL, producer, NULL);
    pthread_create(
    &thread3, NULL, consumer, NULL);

    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    pthread_join(thread3,NULL);
    }
    复制代码

     

     

    注意:要用两个信号量来标示缓冲的大小,这是实现P_C模型的巧妙之处。

    2)图示

    wps_clip_image-8987

    3)函数

    sem_init()用于创建一个信号量,并初始化它的值。

    sem_wait()和sem_trywait()都相当于P操作,在信号量大于零时它们都能将信号量的值减一,两者的区别在于若信号量小于零时,sem_wait()将会阻塞进程,而sem_trywait()则会立即返回。

    sem_post()相当于V操作,它将信号量的值加一同时发出信号来唤醒等待的进程。

    sem_getvalue()用于得到信号量的值。

    sem_destroy()用于删除信号量。

    参考:

    1 http://www.cnblogs.com/mydomain/archive/2011/07/10/2102147.html

    2】 http://blog.csdn.net/lanmoshui963/article/details/2176376

    3】 http://www.cnblogs.com/mydomain/archive/2011/08/14/2138454.html

    4】 华中科技大学,中山大学PPT

  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/qq78292959/p/2864428.html
Copyright © 2011-2022 走看看