From 7d8e55d27547ba77a71d442f730d6f70cd59b40a Mon Sep 17 00:00:00 2001 From: flykhan Date: Tue, 22 Aug 2023 20:46:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E4=BB=BB=E5=8A=A1=E4=BA=92=E6=96=A5?= =?UTF-8?q?=E4=B8=8E=E5=90=8C=E6=AD=A5(=E4=BA=92=E6=96=A5=E9=94=81,=20?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E9=94=81,=20=E6=9D=A1=E4=BB=B6=E5=8F=98?= =?UTF-8?q?=E9=87=8F,=20=E4=BF=A1=E5=8F=B7=E9=87=8F,=20=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E4=BF=A1=E5=8F=B7=E9=87=8F)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day7/condition.c | 83 +++++++++++++++++++++++++++++++++++ day7/mutex_1.c | 58 +++++++++++++++++++++++++ day7/named_sem_1.c | 45 +++++++++++++++++++ day7/named_sem_2.c | 48 +++++++++++++++++++++ day7/named_sem_3.c | 34 +++++++++++++++ day7/named_sem_4.c | 38 ++++++++++++++++ day7/nomutex.c | 28 ++++++++++++ day7/nomutex_2.c | 42 ++++++++++++++++++ day7/nomutex_3.c | 54 +++++++++++++++++++++++ day7/rwlock_1.c | 52 ++++++++++++++++++++++ day7/rwlock_2.c | 97 +++++++++++++++++++++++++++++++++++++++++ day7/sem_1.c | 48 +++++++++++++++++++++ day7/sem_2.c | 105 +++++++++++++++++++++++++++++++++++++++++++++ day7/sem_3.c | 88 +++++++++++++++++++++++++++++++++++++ 14 files changed, 820 insertions(+) create mode 100644 day7/condition.c create mode 100644 day7/mutex_1.c create mode 100644 day7/named_sem_1.c create mode 100644 day7/named_sem_2.c create mode 100644 day7/named_sem_3.c create mode 100644 day7/named_sem_4.c create mode 100644 day7/nomutex.c create mode 100644 day7/nomutex_2.c create mode 100644 day7/nomutex_3.c create mode 100644 day7/rwlock_1.c create mode 100644 day7/rwlock_2.c create mode 100644 day7/sem_1.c create mode 100644 day7/sem_2.c create mode 100644 day7/sem_3.c diff --git a/day7/condition.c b/day7/condition.c new file mode 100644 index 0000000..a56f8fd --- /dev/null +++ b/day7/condition.c @@ -0,0 +1,83 @@ +#include +#include +#include + +// 条件变量实例 + +// 互斥锁和条件变量的初始化 +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + +void *producer_task(void *data) +{ + int *n = (int *)data; + while (1) + { + pthread_mutex_lock(&mutex); + + while (*n == 10) // 只要资源为 10 ,就等待 + { + // 条件变量等待后,会自动释放 mutex 锁 + pthread_cond_wait(&cond, &mutex); + } + + (*n)++; + printf("生产线程(%ld)生产了 %d 个产品\n", pthread_self(), *n); + + // 发出通知,让等待消费的线程恢复(条件满足) + pthread_cond_broadcast(&cond); + + pthread_mutex_unlock(&mutex); + // usleep(200 * 1000); + sleep(1); + } + + pthread_exit(NULL); +} + +void *consumer_task(void *data) +{ + int *n = (int *)data; + while (1) + { + pthread_mutex_lock(&mutex); + while (*n == 0) // 只要资源为 0 ,就等待 + { + // 条件变量等待后,会自动释放 mutex 锁 + pthread_cond_wait(&cond, &mutex); + } + printf("消费者(%ld) 消费了 %d 产品\n", pthread_self(), *n); + (*n)--; + pthread_mutex_unlock(&mutex); + // usleep(200 * 1000); + sleep(1); + } + pthread_exit(NULL); +} + +int main(int argc, char const *argv[]) +{ + int num = 3; // 3 个产品 + pthread_t threads[10]; + // 创建 2 个生产线程 + for (int i = 0; i < 8; i++) + { + pthread_create(&threads[i], NULL, producer_task, &num); + } + + // 创建 3 个消费者线程 + for (int i = 8; i < 10; i++) + { + pthread_create(&threads[i], NULL, consumer_task, &num); + } + + for (int i = 0; i < 10; i++) + { + pthread_join(threads[i], NULL); + } + + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + + return 0; +} diff --git a/day7/mutex_1.c b/day7/mutex_1.c new file mode 100644 index 0000000..f7795e8 --- /dev/null +++ b/day7/mutex_1.c @@ -0,0 +1,58 @@ +#include +#include +#include + +// 定义两把锁 +pthread_mutex_t mutex1, mutex2; + +void *task1(void *data) +{ + char *taskName = (char *)data; + pthread_mutex_lock(&mutex1); + printf("%s 获取锁 1 成功, 等待 1 秒后获取锁 2\n", taskName); + sleep(1); + pthread_mutex_lock(&mutex2); + printf("%s 获取锁 2 成功\n", taskName); + printf("%s\n", taskName); + + // 释放锁 + pthread_mutex_unlock(&mutex2); + pthread_mutex_unlock(&mutex1); + return NULL; +} + +void *task2(void *data) +{ + char *taskName = (char *)data; + pthread_mutex_lock(&mutex1); + printf("%s 获取锁 1 成功, 等待 1 秒后获取锁 2\n", taskName); + sleep(1); + pthread_mutex_lock(&mutex2); + printf("%s 获取锁 2 成功\n", taskName); + printf("%s\n", taskName); + + // 释放锁 + pthread_mutex_unlock(&mutex2); + pthread_mutex_unlock(&mutex1); + return NULL; +} + +int main(int argc, char const *argv[]) +{ + // 动态初始化锁 + pthread_mutex_init(&mutex1, NULL); + pthread_mutex_init(&mutex2, NULL); + + // 创建线程 + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, task1, "hello"); + pthread_create(&tid2, NULL, task2, "world"); + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + + // 销毁锁 + pthread_mutex_destroy(&mutex1); + pthread_mutex_destroy(&mutex2); + + return 0; +} diff --git a/day7/named_sem_1.c b/day7/named_sem_1.c new file mode 100644 index 0000000..ddad100 --- /dev/null +++ b/day7/named_sem_1.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include + +// 命名信号实例 + +void printer(char *msg) +{ + while (*msg) + { + printf("%c", *msg++); // 打印字符 + fflush(stdout); // 刷新控制台 + sleep(1); + } +} + +int main(int argc, char const *argv[]) +{ + // 命名信号 + sem_t *sem = sem_open("mysem", O_CREAT | O_RDWR, 0644, 1); + + int pid = fork(); + if (pid == 0) // 子进程 + { + sem_wait(sem); + printer("disen666"); + sem_post(sem); + _exit(0); + } + else if (pid > 0) // 父进程 + { + sem_wait(sem); + printer("jack888"); + sem_post(sem); + wait(NULL); // 等待子进程退出 + + printf("\n---over---\n"); + sem_close(sem); // 关闭信号量 + sem_unlink("mysem"); // 删除信号量文件 + } + return 0; +} diff --git a/day7/named_sem_2.c b/day7/named_sem_2.c new file mode 100644 index 0000000..e1b9621 --- /dev/null +++ b/day7/named_sem_2.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +// 命名信号实例 + +void printer(char *msg) +{ + while (*msg) + { + printf("%c", *msg++); // 打印字符 + fflush(stdout); // 刷新控制台 + sleep(1); + } +} + +int main(int argc, char const *argv[]) +{ + // 命名信号 + sem_t *sem1 = sem_open("mysem1", O_CREAT | O_RDWR, 0644, 1); + sem_t *sem2 = sem_open("mysem2", O_CREAT | O_RDWR, 0644, 0); + + int pid = fork(); + if (pid == 0) // 子进程 + { + sem_wait(sem1); + printer("disen666"); + sem_post(sem2); + _exit(0); + } + else if (pid > 0) // 父进程 + { + sem_wait(sem2); + printer("jack888"); + sem_post(sem1); + + wait(NULL); // 等待子进程退出 + printf("\n---over---\n"); + sem_close(sem1); // 关闭信号量 + sem_close(sem2); // 关闭信号量 + sem_unlink("mysem1"); // 删除信号量文件 + sem_unlink("mysem2"); // 删除信号量文件 + } + return 0; +} diff --git a/day7/named_sem_3.c b/day7/named_sem_3.c new file mode 100644 index 0000000..9c7dd06 --- /dev/null +++ b/day7/named_sem_3.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include + +// 无血缘关系的进程的互斥 +void printer(char *msg) +{ + while (*msg) + { + printf("%c", *msg++); + fflush(stdout); + sleep(1); + } +} + +int main(int argc, char const *argv[]) +{ + // 打开信号量文件 + sem_t *sem = sem_open("mysem", O_CREAT | O_RDWR, 0666, 1); + + sem_wait(sem); +#ifdef DISEN + printer("disen666\n"); +#else + printer("jack888\n"); +#endif + sem_post(sem); + sem_close(sem); + + return 0; +} diff --git a/day7/named_sem_4.c b/day7/named_sem_4.c new file mode 100644 index 0000000..91f92e2 --- /dev/null +++ b/day7/named_sem_4.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include + +// 无血缘关系的进程的同步 +void printer(char *msg) +{ + while (*msg) + { + printf("%c", *msg++); + fflush(stdout); + sleep(1); + } +} + +int main(int argc, char const *argv[]) +{ + // 打开信号量文件 + sem_t *sem1 = sem_open("mysem1", O_CREAT | O_RDWR, 0666, 1); + sem_t *sem2 = sem_open("mysem2", O_CREAT | O_RDWR, 0666, 0); + +#ifdef DISEN + sem_wait(sem2); + printer("disen666\n"); + sem_post(sem1); +#else + sem_wait(sem1); + printer("jack888\n"); + sem_post(sem2); +#endif + + sem_close(sem1); + sem_close(sem2); + return 0; +} diff --git a/day7/nomutex.c b/day7/nomutex.c new file mode 100644 index 0000000..c90d254 --- /dev/null +++ b/day7/nomutex.c @@ -0,0 +1,28 @@ +#include +#include +#include + +void *printer(void *data) +{ + char *msg = (char *)data; + while (*msg) + { + printf("%c", *msg++); + fflush(stdout); + sleep(1); + } + return NULL; +} + +int main(int argc, char const **argv) +{ + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, printer, "disen666\0"); + pthread_create(&tid2, NULL, printer, "lucy888\0"); + + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("---over---\n"); + + return 0; +} \ No newline at end of file diff --git a/day7/nomutex_2.c b/day7/nomutex_2.c new file mode 100644 index 0000000..8cc0aab --- /dev/null +++ b/day7/nomutex_2.c @@ -0,0 +1,42 @@ +#include +#include +#include + +// 静态初始化互斥锁 +// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +// 动态初始化锁-定义锁 +pthread_mutex_t mutex; + +void *printer(void *data) +{ + + char *msg = (char *)data; + pthread_mutex_lock(&mutex); // 申请上锁,可能阻塞 + while (*msg) + { + printf("%c", *msg++); + fflush(stdout); + usleep(200 * 1000); + } + pthread_mutex_unlock(&mutex); // 不解锁,就会发生死锁 + return NULL; +} + +int main(int argc, char const **argv) +{ + // 动态初始化锁-初始化 + pthread_mutex_init(&mutex, NULL); + + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, printer, "disen666\n"); + pthread_create(&tid2, NULL, printer, "lucy888\n"); + + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("\n---over---\n"); + + // 销毁互斥锁 + pthread_mutex_destroy(&mutex); + + return 0; +} \ No newline at end of file diff --git a/day7/nomutex_3.c b/day7/nomutex_3.c new file mode 100644 index 0000000..e9a2001 --- /dev/null +++ b/day7/nomutex_3.c @@ -0,0 +1,54 @@ +#include +#include +#include + +// 静态初始化互斥锁 +// pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +// 动态初始化锁-定义锁 +pthread_mutex_t mutex; + +void *printer(void *data) +{ + + char *msg = (char *)data; + int lock_acquired = 0; // 未获取到锁 + while (!lock_acquired) // 未获取到锁的时候,循环尝试获取锁,并处理 + { + // trylock 非阻塞锁 + if (pthread_mutex_trylock(&mutex) == 0) // 如果拿到锁 + { + lock_acquired = 1; // 该状态:已获取到锁 + while (*msg) // 当前线程传入的字符串未读取完成时,循环读取 + { + printf("%c", *msg++); + fflush(stdout); + usleep(200 * 1000); + } + pthread_mutex_unlock(&mutex); // 读完后,解锁当前进程 + } + else + { + usleep(100); // 0.1 毫秒后继续尝试获取锁 + } + } + return NULL; +} + +int main(int argc, char const **argv) +{ + // 动态初始化锁-初始化 + pthread_mutex_init(&mutex, NULL); + + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, printer, "disen666\n"); + pthread_create(&tid2, NULL, printer, "lucy888\n"); + + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("\n---over---\n"); + + // 销毁互斥锁 + pthread_mutex_destroy(&mutex); + + return 0; +} \ No newline at end of file diff --git a/day7/rwlock_1.c b/day7/rwlock_1.c new file mode 100644 index 0000000..6d11e9a --- /dev/null +++ b/day7/rwlock_1.c @@ -0,0 +1,52 @@ +#include +#include +#include + +// 定义读写锁(需要 GNU99) +pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; // 静态初始化读写锁 + +void *read_task(void *data) +{ + int *n = (int *)data; + + while (1) + { + pthread_rwlock_rdlock(&rwlock); // 申请读锁 rdlock + printf("(%ld)线程读取 num: %d\n", pthread_self(), *n); + pthread_rwlock_unlock(&rwlock); // 解锁 + usleep(500 * 1000); + } + return NULL; +} + +void *write_task(void *data) +{ + int *n = (int *)data; + while (1) + { + pthread_rwlock_wrlock(&rwlock); // 申请写锁 wrlock + (*n)++; + printf("(%ld) 线程写 num: %d\n", pthread_self(), *n); + pthread_rwlock_unlock(&rwlock); // 解锁 + sleep(2); + } + + return NULL; +} + +int main(int argc, char const *argv[]) +{ + int num; // 公共资源 + pthread_t t1, t2, t3; + pthread_create(&t1, NULL, read_task, &num); + pthread_create(&t2, NULL, read_task, &num); + pthread_create(&t3, NULL, write_task, &num); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + pthread_join(t3, NULL); + + pthread_rwlock_destroy(&rwlock); // 销毁读写锁 + + return 0; +} diff --git a/day7/rwlock_2.c b/day7/rwlock_2.c new file mode 100644 index 0000000..ba228a8 --- /dev/null +++ b/day7/rwlock_2.c @@ -0,0 +1,97 @@ +#include +#include +#include +#include + +pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER; +int money = 1000; // 存款余额 +int exit_flag = 0; // 退出标志 + +void *task1(void *data) +{ + while (1) + { + pthread_rwlock_wrlock(&rwlock); // 加写锁 + // 查询余额 + printf("存款任务-余额: %d\n", money); + usleep(200 * 1000); + // 从键盘读取存入的金额 + printf("请输入存款金额 (输入 0 结束存款): "); + fflush(stdout); + int m; + scanf("%d", &m); + if (m == 0) + { + exit_flag = 1; + pthread_rwlock_unlock(&rwlock); // 解锁 + break; + } + money += m; + // 修改余额并打印结果 + printf("存款成功, 余额为 %d\n", money); + pthread_rwlock_unlock(&rwlock); // 解锁 + } + pthread_exit(NULL); +} + +void *task2(void *data) +{ + while (1) + { + pthread_rwlock_wrlock(&rwlock); // 加写锁 + // 查询余额 + printf("取款任务-余额: %d\n", money); + usleep(200 * 1000); + // 从键盘读取取出的金额 + printf("请输入取款金额 (输入 0 结束取款): "); + fflush(stdout); + int m; + scanf("%d", &m); + if (m == 0) + { + exit_flag = 1; + pthread_rwlock_unlock(&rwlock); // 解锁 + break; + } + if (money >= m) + { + money -= m; + // 修改余额并打印结果 + printf("取款成功, 余额为 %d\n", money); + } + else + { + printf("取款失败, 余额不足\n"); + } + pthread_rwlock_unlock(&rwlock); // 解锁 + } + pthread_exit(NULL); +} + +int main(int argc, char const *argv[]) +{ + while (1) + { + pthread_t t1, t2; + pthread_create(&t1, NULL, task1, NULL); + pthread_create(&t2, NULL, task2, NULL); + + while (1) + { + pthread_rwlock_rdlock(&rwlock); + if (exit_flag) + { + pthread_rwlock_unlock(&rwlock); + break; + } + pthread_rwlock_unlock(&rwlock); + } + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + } + + pthread_rwlock_destroy(&rwlock); + + return 0; +} diff --git a/day7/sem_1.c b/day7/sem_1.c new file mode 100644 index 0000000..a6b6279 --- /dev/null +++ b/day7/sem_1.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +// 信号量实例 + +sem_t sem; // 定义信号量 + +void *printer(void *data) +{ + + char *msg = (char *)data; + + // P 操作 + sem_wait(&sem); // 本案例中锁住了控制台 + + while (*msg) + { + printf("%c", *msg++); + fflush(stdout); + usleep(200 * 1000); + } + + // V 操作 + sem_post(&sem); + + return NULL; +} + +int main(int argc, char const **argv) +{ + // 信号量初始化 + sem_init(&sem, 0, 1); + + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, printer, "disen666\n"); + pthread_create(&tid2, NULL, printer, "lucy888\n"); + + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("\n---over---\n"); + + // 销毁信号量 + sem_destroy(&sem); + + return 0; +} \ No newline at end of file diff --git a/day7/sem_2.c b/day7/sem_2.c new file mode 100644 index 0000000..d79077f --- /dev/null +++ b/day7/sem_2.c @@ -0,0 +1,105 @@ +#include +#include +#include +#include +#include + +// 信号量实例 2 - 存取款 +sem_t sem; // 定义信号量 + +int money = 1000; // 存款余额 +int exit_flag = 0; // 退出标志 + +void *task1(void *data) +{ + while (1) + { + sem_wait(&sem); // P 操作 + // 查询余额 + printf("存款任务-余额: %d\n", money); + usleep(200 * 1000); + // 从键盘读取存入的金额 + printf("请输入存款金额 (输入 0 结束存款): "); + fflush(stdout); + int m; + scanf("%d", &m); + if (m == 0) + { + exit_flag = 1; + sem_post(&sem); // V 操作 + break; + } + money += m; + // 修改余额并打印结果 + printf("存款成功, 余额为 %d\n", money); + sem_post(&sem); // V 操作 + } + pthread_exit(NULL); +} + +void *task2(void *data) +{ + while (1) + { + sem_wait(&sem); // P 操作 + // 查询余额 + printf("取款任务-余额: %d\n", money); + usleep(200 * 1000); + // 从键盘读取取出的金额 + printf("请输入取款金额 (输入 0 结束取款): "); + fflush(stdout); + int m; + scanf("%d", &m); + if (m == 0) + { + exit_flag = 1; + sem_post(&sem); // V 操作 + break; + } + if (money >= m) + { + money -= m; + // 修改余额并打印结果 + printf("取款成功, 余额为 %d\n", money); + } + else + { + printf("取款失败, 余额不足\n"); + } + sem_post(&sem); // V 操作 + } + pthread_exit(NULL); +} + +int main(int argc, char const *argv[]) +{ + // 初始化信号量 + sem_init(&sem, 0, 1); + + while (1) + { + pthread_t t1, t2; + pthread_create(&t1, NULL, task1, NULL); + pthread_create(&t2, NULL, task2, NULL); + + while (1) + { + sem_wait(&sem); // P 操作 + + if (exit_flag) + { + sem_post(&sem); // V 操作 + break; + } + sem_post(&sem); // V 操作 + } + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + } + + // 销毁信号量 + sem_destroy(&sem); + + return 0; +} diff --git a/day7/sem_3.c b/day7/sem_3.c new file mode 100644 index 0000000..8d85a69 --- /dev/null +++ b/day7/sem_3.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +sem_t sem1, sem2; // 信号量 + +void *task1(void *data) +{ + int *money = (int *)data; + // 存款任务 + sem_wait(&sem1); + + // 查询余额 + printf("存款任务-余额: %d\n", *money); + sleep(1); + // 从键盘读取存入的金额 + printf("请输入存款金额: "); + fflush(stdout); + int m; + scanf("%d", &m); + *money += m; + // 修改余额并打印结果 + printf("存款成功, 余额为: %d\n", *money); + sem_post(&sem2); + pthread_exit(NULL); +} + +void *task2(void *data) +{ + int *money = (int *)data; + // 取款任务 + sem_wait(&sem2); + // 查询余额 + printf("取款任务-余额: %d\n", *money); + + sleep(1); + + // 从键盘读取取出的金额 + printf("请输入取款金额: "); + fflush(stdout); + int m; + scanf("%d", &m); + if (*money >= m) + { + *money -= m; + // 修改余额并打印结果 + printf("取款成功, 余额为: %d\n", *money); + } + else + { + printf("取款失败,余额不足\n"); + } + + sem_post(&sem1); + pthread_exit(NULL); +} + +int main(int argc, char const *argv[]) +{ + // 初始化信号量 + sem_init(&sem1, 0, 1); // 存款的信号量初始化 + sem_init(&sem2, 0, 0); // 取款的信号量初始化 + + int money = 1000; // 存款 + + while (1) + { + printf("输入 exit 退出 , 输入其他内容开始存取款\n"); + char input[100]; + scanf("%s", input); + if (strncmp(input, "exit", 4) == 0) + { + break; + } + pthread_t tid1, tid2; + pthread_create(&tid1, NULL, task1, &money); + pthread_create(&tid2, NULL, task2, &money); + + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + } + + sem_destroy(&sem1); + sem_destroy(&sem2); + return 0; +}