零、写在前面
这个系列不经常更新,今天这个题目因为英雄哥玩超纲课后题0.0,我们一起看一看,主要知识点在
【第16题】给定 n,打印一个直角边为 n 的等边直角三角形https://blog.csdn.net/WhereIsHeroFrom/article/details/118272189
https://blog.csdn.net/WhereIsHeroFrom/article/details/118272189
一、主要知识点
1.打印指定的形状的边界判定
#include<stdio.h> int main() { int n, i, j; while(scanf("%d", &n) != EOF) { for(i = 1; i <= n; ++i) { // 打印指定行数 for(j = 1; j <= i; ++j) // 打印数量与行数相同 printf("*"); // 打印字符 printf("\n"); // 换行 } } return 0; }
2.信号量
首先我们了解下进程互斥需要遵循的四个原则。
1.空闲让进 2.忙则等待 3.有限等待 4.让权等待
其中空闲让进、忙则等待保证了进程的互斥访问。有限等待保证了程序的可执行性质。
让权等待指的是在等待的时候主动休眠放弃cpu的使用权力。
而最常用保证上面的这些的一个机制就是信号量,c语言里面有几个常用的函数帮助我们来实现这些操作。
sem_t bar;//创建信号量变量 sem_init(&(obj->foo),0,1);//初始化 其中第一个参数为信号量地址 第二个是共享范围 0表示在所有进程共享 第三个是初始值 一开始拥有的个数 sem_wait(&(obj->foo)); //申请信号量 如果能申请到 就减小信号量的个数 往下执行 否则主动睡眠 sem_post(&(obj->bar)); //释放信号量,给相应的信号量+1,并唤醒相应的进程
二、课后习题
1115. 交替打印FooBar
1115. 交替打印FooBar
https://leetcode-cn.com/problems/print-foobar-alternately/
题目描述
两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
请设计修改程序,以确保 "foobar" 被输出 n 次。
思路
明显的进程同步问题,也就是foo执行一次 far执行一次。一开始就写了一个不遵循让权等待的简单同步模型,你们应该可以看懂-.-
typedef struct { int n; int x; //同步用变量 } FooBar; FooBar* fooBarCreate(int n) { FooBar* obj = (FooBar*) malloc(sizeof(FooBar)); obj->n = n; obj->x = 0;//初始化 return obj; } void foo(FooBar* obj) { for (int i = 0; i < obj->n; i++) { while(obj->x); //等待x为0 // printFoo() outputs "foo". Do not change or remove this line. printFoo(); obj->x=1; /将x设置为1 } } void bar(FooBar* obj) { for (int i = 0; i < obj->n; i++) { while(!obj->x); //等待x为1 // printBar() outputs "bar". Do not change or remove this line. printBar(); obj->x=0; //将x设置为0 } } void fooBarFree(FooBar* obj) { free(obj); }
结果
超时!没错 肯定超时 毕竟一直卡在while里
思路2
利用上面说到的给的信号量。
typedef struct { int n; sem_t foo;//两个信号量 sem_t bar; } FooBar; FooBar* fooBarCreate(int n) { FooBar* obj = (FooBar*) malloc(sizeof(FooBar)); obj->n = n; sem_init(&(obj->foo),0,1);//foo先执行所以给1 sem_init(&(obj->bar),0,0); return obj; } void foo(FooBar* obj) { for (int i = 0; i < obj->n; i++) { sem_wait(&(obj->foo));//请求foo // printFoo() outputs "foo". Do not change or remove this line. printFoo(); sem_post(&(obj->bar));//释放bar } } void bar(FooBar* obj) { for (int i = 0; i < obj->n; i++) { sem_wait(&(obj->bar));//请求bar // printBar() outputs "bar". Do not change or remove this line. printBar(); sem_post(&(obj->foo));//释放foo } } void fooBarFree(FooBar* obj) { sem_destroy(&(obj->bar)); sem_destroy(&(obj->foo)); free(obj); }
写在最后
我还能肝,肝死。。。。大家要加油,无论你们希望成为什么样的人,都需要不焦虑的一步一步靠近它!