加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_汕头站长网 (https://www.0754zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

c linux 线程循环执行

发布时间:2022-10-14 12:59:00 所属栏目:Linux 来源:
导读:  /* Wait until spinlock LOCK is retrieved. */
  extern int pthread_spin_lock (pthread_spinlock_t *__lock)
  作用:用来获取(锁定)指定的自旋锁. 如果该自旋锁当前没有被其它线程所持有,则调用

  /* Wait until spinlock LOCK is retrieved.  */
  extern int pthread_spin_lock (pthread_spinlock_t *__lock)
  作用:用来获取(锁定)指定的自旋锁. 如果该自旋锁当前没有被其它线程所持有,则调用该函数的线程获得该自旋锁.否则该函数在获得自旋锁之前不会返回。如果调用该函数的线程在调用该函数时已经持有了该自旋锁,则结果是不确定的
 
  /* Try to lock spinlock LOCK.  */
  extern int pthread_spin_trylock (pthread_spinlock_t *__lock)
  作用:尝试获取指定的自旋锁,如果无法获取则理解返回失败
 
  /* Release spinlock LOCK.  */
  extern int pthread_spin_unlock (pthread_spinlock_t *__lock)
  作用:用于释放指定的自旋锁
 
  /* Destroy the spinlock LOCK.  */
  extern int pthread_spin_destroy (pthread_spinlock_t *__lock)
  作用:用来销毁指定的自旋锁并释放所有相关联的资源(所谓的所有指的是由pthread_spin_init自动申请的资源)在调用该函数之后如果没有调用 pthread_spin_init重新初始化自旋锁,则任何尝试使用该锁的调用的结果都是未定义的。如果调用该函数时自旋锁正在被使用或者自旋锁未被初 始化则结果是未定义的。
 
  自旋锁的用法和互斥锁基本差不多,对于自旋锁来说,它只需要消耗很少的资源来建立锁;随后当线程被阻塞时,它就会一直重复检查看锁是否可用了,也就是说当自旋锁处于等待状态时它会一直消耗CPU时间。
 
  对于互斥锁来说,与自旋锁相比它需要消耗大量的系统资源来建立锁;随后当线程被阻塞时线程池linux,线程的调度状态被修改,并且线程被加入等待线程队列;最后当锁可用 时,在获取锁之前,线程会被从等待队列取出并更改其调度状态;但是在线程被阻塞期间,它不消耗CPU资源。
 
  因此自旋锁和互斥锁适用于不同的场景。自旋锁适用于那些仅需要阻塞很短时间的场景,而互斥锁适用于那些可能会阻塞很长时间的场景。
 
  此处可以参考:posix多线程有感--自旋锁-taohorse-ChinaUnix博客
 
  直接来看一个自旋锁和互斥锁比较的例子
 
  #include
  #include
  #include
  #include
  #include
  #include
  static int num = 0;
  static int count = 10000000;
  static pthread_spinlock_t spin;
  //static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  void Perror(const char *s)
  {
   perror(s);
   exit(EXIT_FAILURE);
  }
  long long getSystemTime()
  {
    struct timeb t;
    ftime(&t);
    return 1000 * t.time + t.millitm;
  }
  void *fun2()
  {
   pthread_t thread_id = pthread_self();
   printf("the thread2 id is %ld\n",(long)thread_id);
   int i=1;
   for (;i<=count;i++)
   {
   pthread_spin_lock(&spin);
   //pthread_mutex_lock(&mutex);
   num += 1;
   pthread_spin_unlock(&spin);
   //pthread_mutex_unlock(&mutex);
   }
  }
  int main()
  {
   int err;
   pthread_t thread1;
   pthread_t thread2;
   pthread_spin_init(&spin,PTHREAD_PROCESS_PRIVATE);
   thread1 = pthread_self();
   printf("the thread1 id is %ld\n",(long)thread1);
   long long start = getSystemTime();
   err = pthread_create(&thread2,NULL,fun2,NULL);
   if(err != 0)
   {
   Perror("can't create thread2\n");
   }
   int i=1;
   for(;i<=count;i++)
   {
   pthread_spin_lock(&spin);
   //pthread_mutex_lock(&mutex);
   num += 1;
   pthread_spin_unlock(&spin);
   //pthread_mutex_unlock(&mutex);
   }
   pthread_join(thread2 ,NULL);
   long long end = getSystemTime();
   printf("The num is %d, pay %lld ms\n",num,(end-start));
   return 0;
  }
  将一个变量count利用自旋锁和互斥锁逐一的加到20000000,比较两者执行的速度,具体运行的时间读者可以自行在机器上运行。
 
  四:条件变量
 
  互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正在被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新检测条件是否满足。
 
  /* Initialize condition variable COND using attributes ATTR, or use
     the default values if later is NULL.  */
  extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
                                const pthread_condattr_t *__restrict __cond_attr)
  作用:初始化条件变量函数
 
  /* Destroy condition variable COND.  */
  extern int pthread_cond_destroy (pthread_cond_t *__cond)
  作用:释放条件变量函数
 
  /* Wake up one thread waiting for condition variable COND.  */
  extern int pthread_cond_signal (pthread_cond_t *__cond)
  作用: 唤醒一个阻塞在条件变量cond上的线程。
 
  /* Wake up all threads waiting for condition variables COND.  */
  extern int pthread_cond_broadcast (pthread_cond_t *__cond)
  作用:用来唤醒所有被阻塞在条件变量cond上的线程。这些线程被唤醒后将再次竞争相应的互斥锁,得小心使用这个函数
 
  /* Wait for condition variable COND to be signaled or broadcast.
     MUTEX is assumed to be locked before.
     This function is a cancellation point and therefore not marked with
     __THROW.  */
  extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
                                pthread_mutex_t *__restrict __mutex)
  作用:使线程阻塞在一个条件变量上
 
  来看一个例子
 
  #include
  #include
  #include
  #include
  static pthread_mutex_t mtx=PTHREAD_MUTEX_INITIALIZER;
  static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
  struct node
  {
   int n_number;
   struct node *next;
  }*head=NULL;
  static void *thread_func()
  {
   struct node *p=NULL;
   while(1)
   {
   pthread_mutex_lock(&mtx);
   //printf("the head is %d\n",head);
   while(head == NULL)
   {
   pthread_cond_wait(&cond,&mtx);
   }
   p=head;
   head=head->next;
   printf("Got %d from front of queue\n",p->n_number);
   free(p);
   p=NULL;
   pthread_mutex_unlock(&mtx);   //临界区数据操作完毕,释放互斥锁
   }
   return 0;
  }
  int main()
  {
   pthread_t tid;
   int i;
   struct node *p;
   pthread_cond_init(&cond,NULL);
   pthread_create(&tid,NULL,thread_func,NULL);
   for(i=0;i<10;i++)
   {
   p = (struct node *)malloc(sizeof(struct node));
   p->n_number = i;
   pthread_mutex_lock(&mtx);
   p->next=head;
   head = p;
   if(p->n_number % 9 == 0)
   pthread_cond_signal(&cond);
   pthread_mutex_unlock(&mtx);
   printf("the i is %d\n",i);
   //printf("the head is %d\n",head);
   sleep(1);
   }
   //printf("head data is %d\n",head->n_number);
   printf("thread 1 wanna end the line.So cancel thread 2.\n");
   pthread_cancel(tid);
   pthread_join(tid,NULL);
   printf("All done------------exiting\n");
   return 0;
  }
  运行结果
 
  [root@ftz c_test]# ./pthread_cond
  the i is 0
  Got 0 from front of queue
  the i is 1
  the i is 2
  the i is 3
  the i is 4
  the i is 5
  the i is 6
  the i is 7
  the i is 8
  the i is 9
  Got 9 from front of queue
  Got 8 from front of queue
  Got 7 from front of queue
  Got 6 from front of queue
  Got 5 from front of queue
  Got 4 from front of queue
  Got 3 from front of queue
  Got 2 from front of queue
  Got 1 from front of queue
  thread 1 wanna end the line.So cancel thread 2.
  All done------------exiting
  从运行结果中可以看到,当最开始head=null时,线程thread_func里的判断条件满足,线程处于阻塞状态,在主程序里,运行到if(p->n_number % 9 == 0),判断条件也满足,此时运行
 
  pthread_cond_signal(&cond);唤醒处于阻塞状态的线程thread_func,有一个打印Got 0 from front of queue。此时head再次等于NULL,满足阻塞条件,但是在主线程里要一直等到p->n_number=9才能再次唤醒线程
 

(编辑:云计算网_汕头站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!