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

c linux 创建挂起线程

发布时间:2022-12-01 12:57:55 所属栏目:Linux 来源:
导读:  若线程创建成功,则返回0;若线程创建失败,则返回出错编号。

  使用示例

  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #
  若线程创建成功,则返回0;若线程创建失败,则返回出错编号。
 
  使用示例
 
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  void *thread_fun(void *arg) {
      printf("My pid is %d, my tid is %u.\n", getpid(), *((unsigned int *)arg));
  }
  int main() {
      pthread_t tid;
      printf("My pid is %d, my tid is %u.\n", getpid(), (unsigned int)pthread_self());
      if (pthread_create(&tid, NULL, thread_fun, (void *)(&tid)) != 0) {
          perror("Create error");
          exit(1);
      }
      pause();
      return 0;
  }
  执行结果
 
  atreus@atreus-virtual-machine:~/code/220317$ make
  gcc main.c -o main -pthread
  atreus@atreus-virtual-machine:~/code/220317$ ./main
  My pid is 54660, my tid is 1044952896.
  My pid is 54660, my tid is 1044948736.
  ^C
  atreus@atreus-virtual-machine:~/code/220317$
  二、线程退出
 
  #include
  int pthread_cancel(pthread_t thread);
  void pthread_exit(void *retval);
  Compile and link with -pthread.
  pthread_cancel()会发送终止信号给目标线程,如果成功则返回0,否则为非0值。但发送成功并不意味着目标线程一定会终止,目标线程收到终止信号后可以终止,也可以忽略,由其自己决定。线程取消是被动退出。
 
  pthread_exit()函数用于线程的主动退出,可以指定返回值,其他线程可以通过pthread_join()函数获取该线程的返回值。当然,对于线程函数使用return返回也可以使线程退出。但不能使用exit退出,会导致进程退出。
 
  三、线程等待&线程状态
 
  #include
  int pthread_join(pthread_t thread, void **retval);
  int pthread_detach(pthread_t thread);
  Compile and link with -pthread.
  线程等待的目的就是保证线程的资源能够被回收,线程有两种状态:
 
  默认情况下,线程会被创建成可结合态的。可结合线程需要主线程调用pthread_join()函数将其资源回收,或者调用pthread_detach()函数将其变为分离态线程,待线程结束时由系统回收其资源。
 
  使用示例
 
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  void *thread1_fun(void *arg) {
      pthread_detach(pthread_self());//将本线程转换为分离态,由系统自动回收资源
      pthread_exit(NULL);
  }
  void *thread2_fun(void *arg) {
      pthread_exit(NULL);
  }
  int main() {
      pthread_t tid1, tid2;
      if (pthread_create(&tid1, NULL, thread1_fun, NULL) != 0) {
          perror("Create error");
          exit(1);
      }
      if (pthread_create(&tid2, NULL, thread2_fun, NULL) != 0) {
          perror("Create error");
          exit(1);
      }
   /* pthread_detach(tid1); */
      pthread_join(tid2, NULL);//等待子线程的结束,在其结束后回收其资源
      return 0;
  }
  –
 
  四、线程同步 1.匿名信号量
 
  #include
  int sem_init(sem_t *sem, int pshared, unsigned int value);
  Link with -pthread.
  sem_init()函数用于初始化一个信号量。sem是指向待操作信号量的指针,pshared如果为0则表示线程间信号量,如果非零则表示定位在共享内存中的进程间信号量,value指定信号量初始化的值。
 
  #include
  int sem_wait(sem_t *sem);
  int sem_trywait(sem_t *sem);
  int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
  Link with -pthread.
  sem_wait()函数用于执行P操作,且为阻塞等待。sem_trywait()函数为非阻塞等待,执行失败会直接返回。sem_timedwait()函数也为阻塞等待,但可以通过abs_timeout参数设置等待时间。
 
  #include
  int sem_post(sem_t *sem);
  Link with -pthread.
  sem_post()函数用于执行V操作。
 
  #include
  int sem_destroy(sem_t *sem);
  Link with -pthread.
  sem_destroy()函数用于销毁一个匿名信号量,在Linux中省略这个函数不会带来异常,但为了安全性和可移植性,还是应该在合适的时机销毁信号量。
 
  通过匿名信号量实现互斥
 
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  sem_t sem[1];
  int sum = 0;
  void *thread1_fun(void *arg);
  void *thread2_fun(void *arg);
  int main() {
      pthread_t tid1, tid2;
      /* 初始化信号量 */
      sem_init(&sem[0], 0, 1);
      
      /* 创建子线程 */
      if (pthread_create(&tid1, NULL, thread1_fun, NULL) != 0) {
          perror("pthread_create(&tid1, NULL, thread1_fun, NULL");
          exit(1);
      }
      if (pthread_create(&tid2, NULL, thread2_fun, NULL) != 0) {
          perror("pthread_create(&tid2, NULL, thread2_fun, NULL");
          exit(1);
      }
      /* 等待子线程退出 */
      pthread_join(tid1, NULL);
      pthread_join(tid2, NULL);
      /* 销毁信号量 */
      sem_destroy(&sem[0]);
      return 0;
  }
  void *thread1_fun(void *arg) {
      sem_wait(&sem[0]);//P
      printf("[1] sum = %d.\n", sum);
      sleep(1);
      sum++;
      printf("[1] sum = %d.\n", sum);
      sleep(1);
      sem_post(&sem[0]);//V
      pthread_exit(NULL);
  }
  void *thread2_fun(void *arg) {
      sem_wait(&sem[0]);//P
      printf("[2] sum = %d.\n", sum);
      sleep(1);
      sum++;
      printf("[2] sum = %d.\n", sum);
      sleep(1);
      sem_post(&sem[0]);//V
      
      pthread_exit(NULL);
  }
  2.互斥锁
 
  通过互斥锁实现互斥
 
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  pthread_mutex_t mutex;
  int sum = 0;
  void *thread_add_fun(void *arg);
  void *thread_show_fun(void *arg);
  int main() {
      pthread_t tid_add, tid_show;
      /* 初始化互斥锁 */
      pthread_mutex_init(&mutex, NULL);
      /* 创建子线程 */
      if (pthread_create(&tid_add, NULL, thread_add_fun, NULL) != 0) {
          perror("pthread_create(&tid_add, NULL, thread_add_fun, NULL");
          exit(1);
      }
      if (pthread_create(&tid_show, NULL, thread_show_fun, NULL) != 0) {
          perror("pthread_create(&tid_show, NULL, thread_show_fun, NULL");
          exit(1);
      }
      /* 等待子线程退出 */
      pthread_join(tid_add, NULL);
      pthread_join(tid_show, NULL);
      /* 销毁互斥锁 */
      pthread_mutex_destroy(&mutex);
      return 0;
  }
  /* 将全局变量增加到3 */
  void *thread_add_fun(void *arg) {
      sleep(1);//将锁让给show线程
      while (sum != 3) {
          pthread_mutex_lock(&mutex);
          sum = sum + 1;
          printf("[add] sum = %d.\n", sum);
          sleep(1);//给show线程获得锁的机会
          pthread_mutex_unlock(&mutex);
      }
  }
  /* 当sum增加到3后将sum输出 */
  void *thread_show_fun(void *arg) {
      pthread_mutex_lock(&mutex);
      printf("[show] wait...\n");
      if (sum != 3) pthread_mutex_unlock(&mutex);
      while (1) {//死循环等待,会一直占用处理机
          pthread_mutex_lock(&mutex);
          if (sum == 3) {
              /* 满足条件输出后把锁释放 */
              printf("[show] sum = %d.\n", sum);
              pthread_mutex_unlock(&mutex);
              break;
          } else {
              /* 不满足条件直接释放锁 */
              pthread_mutex_unlock(&mutex);
          }
      }
  }
  执行结果
 
  atreus@atreus-virtual-machine:~/code/220317$ make
  gcc main.c -o main -pthread
  atreus@atreus-virtual-machine:~/code/220317$ ./main
  [show] wait...
  [add] sum = 1.
  [add] sum = 2.
  [add] sum = 3.
  [show] sum = 3.
  atreus@atreus-virtual-machine:~/code/220317$
  3.条件变量
 
  通过条件变量和互斥锁实现互斥(改进互斥锁)
 
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  pthread_mutex_t mutex;
  pthread_cond_t cond;
  int sum = 0;
  void *thread_add_fun(void *arg);
  void *thread_show_fun(void *arg);
  int main() {
      pthread_t tid_add, tid_show;
      /* 初始化互斥锁和条件变量 */
      pthread_mutex_init(&mutex, NULL);
      pthread_cond_init(&cond, NULL);
      /* 创建子线程 */
      if (pthread_create(&tid_add, NULL, thread_add_fun, NULL) != 0) {
          perror("pthread_create(&tid_add, NULL, thread_add_fun, NULL");
          exit(1);
      }
      if (pthread_create(&tid_show, NULL, thread_show_fun, NULL) != 0) {
          perror("pthread_create(&tid_show, NULL, thread_show_fun, NULL");
          exit(1);
      }
      /* 等待子线程退出 */
      pthread_join(tid_add, NULL);
      pthread_join(tid_show, NULL);
      /* 销毁互斥锁和条件变量 */
      pthread_mutex_destroy(&mutex);
      pthread_cond_destroy(&cond);
      return 0;
  }
  /* 将全局变量增加到3 */
  void *thread_add_fun(void *arg) {
      sleep(1);//将锁让给show线程
      while (sum != 3) {
          pthread_mutex_lock(&mutex);
          sum = sum + 1;
          printf("[add] sum = %d.\n", sum);
          sleep(1);
          if (sum == 3) pthread_cond_signal(&cond);//满足要求,唤醒show线程
          pthread_mutex_unlock(&mutex);
      }
  }
  /* 当sum增加到3后将sum输出 */
  void *thread_show_fun(void *arg) {
      pthread_mutex_lock(&mutex);
      printf("[show] wait...\n");
      if (sum != 3) pthread_cond_wait(&cond, &mutex);//不满足要求,挂起自己,等待add线程
      printf("[show] sum = %d.\n", sum);
  }
  执行结果
 
  atreus@atreus-virtual-machine:~/code/220317$ make
  gcc main.c -o main -pthread
  atreus@atreus-virtual-machine:~/code/220317$ ./main
  [show] wait...
  [add] sum = 1.
  [add] sum = 2.
  [add] sum = 3.
  [show] sum = 3.
  atreus@atreus-virtual-machine:~/code/220317$
  通过执行结果可以看出,show函数在获得锁后发现sum不等于3,于是将锁释放并将自己挂起,add函数获得锁后执行自加线程池linux,在加到3后唤起show函数完成输出。这样就通过条件变量避免了死循环等待导致的资源占用。
 
  其中,pthread_cond_wait函数并非只是单独地等待条件变量,因为我们注意到参数列表中除了条件变量外,还包括一个互斥锁。实际上,pthread_cond_wait会依次执行以下操作:
 
  调用者线程首先释放互斥锁;然后阻塞,等待被别的线程唤醒;当调用者线程被唤醒后,调用者线程会再次获取互斥锁。
 
  比如以下代码:
 
  #include
  #include
  #include
  pthread_mutex_t mutex;
  pthread_cond_t cond;
  void *addNumer(void *arg) {
      pthread_mutex_lock(&mutex);
      printf("Waiting cond.\n");
      pthread_cond_wait(&cond, &mutex);
      pthread_mutex_unlock(&mutex);
      return NULL;
  }
  int main() {
      pthread_t thread1, thread2;
      pthread_mutex_init(&mutex, NULL);
      pthread_cond_init(&cond, NULL);
      pthread_create(&thread1, NULL, addNumer, NULL);
      pthread_create(&thread2, NULL, addNumer, NULL);
      sleep(5);
      printf("The pthread_cond_broadcast() will be used soon.\n");
      pthread_cond_broadcast(&cond);
      pthread_join(thread1, NULL);
      pthread_join(thread2, NULL);
      pthread_mutex_destroy(&mutex);
      pthread_cond_destroy(&cond);
      return 0;
  }
  atreus@AtreusdeMacBook-Pro % gcc code.c -o code -lpthread
  atreus@AtreusdeMacBook-Pro % ./code                      
  Waiting cond.
  Waiting cond.
  The pthread_cond_broadcast() will be used soon.
  atreus@AtreusdeMacBook-Pro %
  可以看到,在pthread_cond_broadcast(&cond)执行前,两个子线程已经分别抢到了互斥锁。
 

(编辑:我爱制作网_沈阳站长网)

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