头歌课堂练习5:进程的同步与互斥

这篇具有很好参考价值的文章主要介绍了头歌课堂练习5:进程的同步与互斥。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一关 多线程编程

//创建多线程的函数pthread_create原型如下:
pthread_create(pthread_t *tidp, const pthread_attr_t *attr,
    (void*)(*start_rtn)(void*), void *arg);

*tidppthread_t类型,也就是指向线程标识符的指针
通俗来讲,要开一个新线程,
那么就得新定义一个pthread_t类型的指针。

*arrtpthread_arrt_t类型
说的是用来设置线程属性,我还没怎么接触这个
一般用NULL

*strat_rtn 是这里 (void*)(*hh)(void*)类型
是线程运行函数的起始地址
虽然上面说的很复杂,但说简单点,就是得
这样命名 void *p(); 就可以用了

*arg 最后一个参数是运行函数的参数。
很简单

pthread_join();

如果主线程结束时,子线程还没有结束,那么子线程会被操作系统杀死。可以在主线程中使用 pthread_join 来等待子线程结束。

关于题目:把一个有两个进程的改成三个进程
原题目:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int sum1 = 0, sum2 = 0;

void *p1(){
  int i, tmp = 0;
  for (i = 1; i <= 100; i++)
    tmp += i;
  sum1 += tmp;
}

void *p2(){
  int i, tmp = 0;
  for (i = 101; i <= 200; i++)
    tmp += i;
  sum2 += tmp;
}

void p3(){
  printf("sum: %d\n", sum1 + sum2);
}

int main(){
  int res;
  pthread_t t;
  void *thread_result;
  res = pthread_create(&t, NULL, p1, NULL);
  if (res != 0){
    perror("failed to create thread");
    exit(1);
  }
  p2();
  res = pthread_join(t, &thread_result);
  if (res != 0){
    perror("failed to join thread");
    exit(2);
  }
  p3();
  return 0;
}

改后如下:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

int sum1 = 0, sum2 = 0;

void *p1(){
  int i, tmp = 0;
  for (i = 1; i <= 100; i++)
    tmp += i;
  sum1 += tmp;
}

void *p2(){
  int i, tmp = 0;
  for (i = 101; i <= 200; i++)
    tmp += i;
  sum2 += tmp;
}

void p3(){
  printf("sum: %d\n", sum1 + sum2);
}

int main(){
  int res;
  pthread_t t1;
  pthread_t t2; //像这里,就是开一个新线程
  void *thread_result;
  res = pthread_create(&t1, NULL, p1, NULL);
  if (res != 0){
    perror("failed to create thread");
    exit(1);
  }
  res = pthread_create(&t2, NULL, p2, NULL);
  //在这里,加一个线程,就是开一个新的。
  if (res != 0){
    perror("failed to join thread");
    exit(2);
  }
  res = pthread_join(t1, &thread_result);
  res = pthread_join(t2, &thread_result);
  //这里再加这个
  p3();
  return 0;
}

最后总结:是学的云里雾里,最后查网络上
main函数也是一个进程
先用pthread_t 新定义一个新的指针,再
void *thread_result;我也不知道这个具体的什么,反正后面要用到
pthread(指针, NULL, 函数, NULL) 创建一个新进程
在最后
pthread_join(t,&thread_result);
然后完成。

第二关

程序 4.c 模拟了如下场景:某休息厅里有足够多(10 把以上)的椅子,10 位顾客先后进入休息厅寻找空椅子,找到后开始在椅子上休息,休息完后让出空椅子、退出休息厅。请只在该程序中插入一些代码(不删除现有代码),来将上述场景调整为休息厅里只有 2 把椅子。
这个题简单,
以下直接来答案:
头歌课堂练习5:进程的同步与互斥

源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define CUSTOMER_NUM  2

int customer_state[CUSTOMER_NUM] = {0};

void sleep_random(int t) {
  sleep((int)(t * (rand() / (RAND_MAX *1.0))));
}

void print_cur_state() {
  int i;
  printf("  customers with seats: (");
  for (i = 0; i < CUSTOMER_NUM; i++)
  {
    if (0 != customer_state[i])
      printf(" %d", i+1);
  }
  printf(" )\n");
}

void *customer(void *id)
{
  const int myid = *(int*)id;
  sleep_random(2);
  printf("customer %d: try to get a seat...\n", myid);

  printf("customer %d: sit down\n", myid);
  customer_state[myid-1] = 1;
  print_cur_state();

  sleep_random(3);

  printf("customer %d: stand up\n", myid);
  customer_state[myid-1] = 0;
  print_cur_state();
}

int main()
{
  int i, id[CUSTOMER_NUM], res;
  pthread_t t[CUSTOMER_NUM];

  srand((int)time(0));

  for (i = 0; i < CUSTOMER_NUM; i++)
  {
    id[i] = i + 1;
    pthread_create(&t[i], NULL, customer, &id[i]);
  }
  for (i = 0; i < CUSTOMER_NUM; i++)
  {
    res = pthread_join(t[i], NULL);
    if (res != 0){
      perror("failed to join thread");
      exit(2);
    }
  }
  return 0;
}

第三关

程序 9.c 实现了哲学家就餐问题,里面存在死锁问题,请用资源顺序分配法改写该程序,避免死锁。

待加入:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

void sleep_random(int t) {
  sleep((int)(t * (rand() / (RAND_MAX *1.0))));
}

void delay(){
  int i = 10000000;
  while (i--)
    ;
}

#define N  5
sem_t chopstick[N];

void *phi(void *id){  /* 'id' starts from 1 */
  int i, left, right, myid = *(int*)id;
  left = myid - 1;
  right = (myid < N) ? myid : 0;
  for (i = 0; i < 3; i++){
    printf("phi #%d: start of thinking\n", myid);
/**** start *************/

      sem_wait(&chopstick[left]);
      delay();
      sem_wait(&chopstick[right]);

/**** end ***************/
    printf("phi #%d: start of eating\n", myid);
    sleep_random(3);
    sem_post(&chopstick[left]);
    sem_post(&chopstick[right]);
    printf("phi #%d: end of eating\n", myid);
  }
}

int main(){
  int i, id[N];
  pthread_t t[N];
  srand((int)time(0));
  for (i = 0; i < N; i++){
    id[i] = i + 1;
    sem_init(&chopstick[i], 0, 1);
  }
  for (i = 0; i < N; i++)
    pthread_create(&t[i], NULL, phi, &id[i]);
  for (i = 0; i < N; i++)
    pthread_join(t[i], NULL);
  return 0;
}

其实很简单,有一种避免什么死循环的意思
加点条件束缚住。。。文章来源地址https://www.toymoban.com/news/detail-444803.html

/* start */
    if(left<right){
      sem_wait(&chopstick[left]);
      delay();
      sem_wait(&chopstick[right]);
    }
    else
    {
      sem_wait(&chostick[right]);
      delay();
      sem_wait(&chostick[left]);
    }
/* end */

到了这里,关于头歌课堂练习5:进程的同步与互斥的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 操作系统-进程和线程-同步、互斥、死锁

    目录 一、同步互斥  二、互斥的实现方法 2.1软件实现 2.1.1单标志法 2.1.2双标志先检查 2.1.3双标志后检查 2.1.4Petersons算法 2.2硬件实现 2.2.1 TestAndSet指令 2.2.2 Swap指令   三、信号量机制 3.1整形变量  3.2 记录型变量  3.3用信号量实现进程互斥、同步、前驱关系 3.3.1互斥  3.3.2同步

    2024年02月08日
    浏览(52)
  • 头歌操作系统2023春季课堂练习1:环境体验

    任务描述 欢迎进行 Linux 世界,当你下载、安装了某个 Linux 发行版,体验了 Linux 桌面并安装了一些你喜爱和需要的软件之后,应该去了解下 Linux 真正的魅力所在:命令行。 每一个 Linux 命令其实就是一个程序,借助这些命令,我们可以办到非常多的事情。 第一个任务就是了

    2024年02月08日
    浏览(73)
  • 头歌操作系统 课堂练习2.1 外部中断 答案

    第一关:时钟中断的发生 作答要求: 根据相关知识进行实际操作,一直输入 c 直到 0/1 将第一行完全填满。回答问题:当第一行 0/1 字符全部输出完毕的时候一共发生了几次时钟中断,即第一行完全填满时 jiffies 记录的已发生次数为多少? 一、设置版本1内核为分析对象 首先

    2024年02月12日
    浏览(119)
  • Linux——线程3|线程互斥和同步

    我们上一篇提到过,多个线程执行下面代码可能会出错,具体原因可查看上一篇Linux博客。 为避免这种错误的出现,我们可采用加锁保护。 PTHREAD_MUTEX_INITIALIZER 用pthread_mutex_t定义一把锁。ptherad_mutex_init是对锁进行初始化的函数。如果这把锁是全局的并且是静态定义的,我们可

    2024年02月05日
    浏览(48)
  • 【Linux】线程同步和互斥

    1.临界资源:多线程执行流共享的资源,且一次只能允许一个执行流访问的资源就叫做临界资源。(多线程、多进程打印数据) 2.临界区:每个线程内部,访问临界资源的代码,就叫做临界区。 3.互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对

    2024年02月08日
    浏览(46)
  • 线程同步与互斥

    目录 前言:基于多线程不安全并行抢票 一、线程互斥锁 mutex 1.1 加锁解锁处理多线程并发  1.2 如何看待锁 1.3 如何理解加锁解锁的本质 1.4 C++RAII方格设计封装锁 前言:基于线程安全的不合理竞争资源 二、线程同步 1.1 线程同步处理抢票 1.2 如何理解\\\"条件变量\\\" 1.3 如何理解条

    2024年02月10日
    浏览(35)
  • Linux——线程的同步与互斥

    目录 模拟抢火车票的过程 代码示例 thread.cc Thread.hpp 运行结果 分析原因 tickets减到-2的本质  解决抢票出错的方案 临界资源的概念 原子性的概念 加锁 定义 初始化 销毁 代码形式如下 代码示例1: 代码示例2: 总结 如何看待锁 申请失败将会阻塞  pthread_mutex_tyrlock 互斥锁实现

    2024年02月06日
    浏览(43)
  • Linux——多线程,互斥与同步

    目录 一.linux互斥 1.进程线程间的互斥相关背景概念 2.互斥量mutex 3.加锁互斥锁mutex 4.锁的底层原理  二.可重入VS线程安全 1.概念 2.常见的线程不安全的情况 3.常见的线程安全的情况  4.常见不可重入的情况  5..常见可重入的情况 6.可重入与线程安全联系  三.死锁 1.死锁四个必

    2024年02月05日
    浏览(34)
  • 【Linux】多线程互斥与同步

    互斥 指的是一种机制,用于确保在同一时刻只有一个进程或线程能够访问共享资源或执行临界区代码。 互斥的目的是 防止多个并发执行的进程或线程访问共享资源时产生竞争条件,从而保证数据的一致性和正确性 ,下面我们来使用多线程来模拟实现一个抢票的场景,看看所

    2024年02月09日
    浏览(40)
  • Linux-线程的同步与互斥

    🚀 临界资源:多线程指行流共享的资源叫做临界资源。 🚀 临界区:每个线程内部访问临界资源的代码片段叫做临界区。 🚀 互斥:任何时刻,互斥保证只有一个指行流进入临界区,访问临界资源,通常是对临界区起保护作用。 🚀 原子性:不被任何调度所打断的操作,该

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包