互斥信号量代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
sem_t sem;
pthread_t id[2];
void *write_data1(void *arg)
{
int fd = *(int *)arg;
while (1)
{
// int sem_wait(sem_t * sem); // 阻塞p操作
sem_wait(&sem);
/**
* 功能:阻塞p操作集合中某个信号量,值-1
* 如果能够p操作成功最好,否则就阻塞直到p操作操作成功为止。
* · 返回值:成功返回0,失败返回-1,errno被设置。
* · 参数:p操作的某个信号量。
* 比如:sem_wait(&sem[0]);
**/
write(fd, "hello", 5);
write(fd, "world", 5);
write(fd, "\n", 1);
// int sem_post(sem_t * sem);
sem_post(&sem);
/**
* 功能:对某个信号量进行v操作,v操作不存在阻塞问题。v操作成功后,信号量的值会+1
* 返回值:成功返回0,失败返回-1,errno被设置。
**/
}
}
void *write_data2(void *arg)
{
int fd = *(int *)arg;
while (1)
{
sem_wait(&sem);
write(fd, "hhhhh", 5);
write(fd, "wwwww", 5);
write(fd, "\n", 1);
sem_post(&sem);
}
}
void my_exit(int sig)
{
for (int i = 0; i < 2; i++)
{
pthread_cancel(id[i]);
}
// int sem_destroy(sem_t * sem);
sem_destroy(&sem);
/**
* 功能:删除某个信号量,把所有信号量都删除后,信号量集合就被销毁。
* 这与删除进程信号量集合有所不同,对于进程信号量集合来说,只要删除一个信号量,
* 整个集合即被删除,但是对于线程信号量来说,需要一个一个的删除,
* 当所有信号量都删除完后,集合才被删除完毕。
*/
}
int main(int argc, char const *argv[])
{
signal(SIGINT, my_exit);
int fd = open("a.txt", O_RDWR | O_CREAT | O_TRUNC, 0655);
if (fd == -1)
{
perror("open file error");
exit(1);
}
// int sem_init(sem_t * sem, int pshared, unsigned int value);// 初始化信号量
sem_init(&sem, 0, 1);
/**
* · 功能:初始化线程信号量集合中的某个信号量,给它设置一个初始值。
* · 返回值
* 成功返回0,失败返回-1,errno被设置。
* 注意信号量的错误号不是返回的,而是设置到errno中。
* 参数
* - sem:信号量集合中的某个信号量信号量集合需要我们自己定义,
* 比如:sem_t sem[3],线程信号量集合其实就是一个数组,数组每个元素就是一个信号量。
* sem[0]:第一个信号量
* sem[1]:第二个信号量
* sem[2]:第三个信号量
* sem_init(&sem[0], int pshared, unsigned int value);
* 线程信号量集合其实就是自定义的一个数组,而进程信号量集合则是通过semget函数创建的。
* 我们只要把数组定义为全局变量,所有的线程即可共享使用,不像进程信号量,需要semid才能实现共享操作。
* - pshared:
* 0:给线程使用
* !0:可以给进程使用不过对于进程来说,我们更多的还是使用进程信号量,因为线程信号量用到进程上时,存在一些不稳定的情况。
* - value:初始化值对于二值信号量来说,要么是1,要么是0。
**/
int ret;
void *(*func_array[2])(void *); // 函数指针数组
func_array[0] = write_data1;
func_array[1] = write_data2;
for (int i = 0; i < 2; i++)
{
ret = pthread_create(id + i, NULL, func_array[i], (void *)&fd);
if (ret < 0)
{
perror("thread error");
exit(1);
}
pthread_detach(id[i]); // 由结合态转变到分离态 ---- 自动回收
}
pause();
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------
同步操作:
有四个进程1、2、3、4。线程1的功能就是输出A,线程2的功能就是输出B,以此类推.........现在有四个文件ABCD。初始都为空。现要让四个文件呈如下格式:
A:A B C D A B....
B:B C D A B C....
C:C D A B C D....
D:D A B C D A....
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
pthread_t ids[4];
int fds[4];
sem_t sems[4];
void my_exit(int sig)
{
for (int i = 0; i < 4; i++)
{
pthread_cancel(ids[i]);
sem_destroy(sems + i);
}
}
void *write_A(void *arg)
{
int flag = 0;
char temp = 'A';
while (1)
{
sem_wait(&sems[0]);
for (int i = 0; i < 4; i++)
{
if (flag != 0 || i <= 0)
{
write(fds[i], &temp, 1);
}
}
flag = 1;
sem_post(&sems[1]);
}
}
void *write_B(void *arg)
{
int flag = 0;
char temp = 'B';
while (1)
{
sem_wait(&sems[1]);
for (int i = 0; i < 4; i++)
{
if (flag != 0 || i <= 1)
{
write(fds[i], &temp, 1);
}
}
flag = 1;
sem_post(&sems[2]);
}
}
void *write_C(void *arg)
{
int flag = 0;
char temp = 'C';
while (1)
{
sem_wait(&sems[2]);
for (int i = 0; i < 4; i++)
{
if (flag != 0 || i <= 2)
{
write(fds[i], &temp, 1);
}
}
flag = 1;
sem_post(&sems[3]);
}
}
void *write_D(void *arg)
{
int flag = 0;
char temp = 'D';
while (1)
{
sem_wait(&sems[3]);
for (int i = 0; i < 4; i++)
{
if (flag != 0 || i <= 3)
{
write(fds[i], &temp, 1);
}
}
flag = 1;
sem_post(&sems[0]);
}
}
void open_file()
{
char temp[1] = "A";
for (int i = 0; i < 4; i++)
{
temp[0] = 'A';
temp[0] = temp[0] + i;
if ((fds[i] = open(temp, O_RDWR | O_CREAT | O_TRUNC, 0655)) < 0)
{
perror("open file error");
exit(1);
}
}
}
void init_sems()
{
for (int i = 0; i < 4; i++) // 只放开A
{
if (i == 0)
{
sem_init(sems + i, 0, 1);
}
else
{
sem_init(sems + i, 0, 0);
}
}
}
int main(int argc, char const *argv[])
{
int ret;
open_file();
init_sems();
signal(SIGINT, my_exit);
void *(*p_func[4])(void *) = {write_A, write_B, write_C, write_D};
for (int i = 0; i < 4; i++)
{
ret = pthread_create(ids + i, NULL, p_func[i], NULL);
if (ret < 0)
{
perror("pthread create error");
exit(1);
}
pthread_detach(ids[i]);
}
pause();
return 0;
}
优化版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
pthread_t ids[4];
int fds[4];
sem_t sems[4];
void my_exit(int sig)
{
for (int i = 0; i < 4; i++)
{
pthread_cancel(ids[i]);
sem_destroy(sems + i);
}
}
void *write_data(void *arg)
{
int flag = 0;
int num = *(int *)arg;
char temp = 'A' + num;
while (1)
{
sem_wait(&sems[num]);
for (int i = 0; i < 4; i++)
{
if (flag != 0 || i <= num)
{
write(fds[i], &temp, 1);
}
}
flag = 1;
sem_post(&sems[(num + 1) % 4]);
}
}
void open_file()
{
char temp[1] = "A";
for (int i = 0; i < 4; i++)
{
temp[0] = 'A';
temp[0] = temp[0] + i;
if ((fds[i] = open(temp, O_RDWR | O_CREAT | O_TRUNC, 0655)) < 0)
{
perror("open file error");
exit(1);
}
}
}
void init_sems()
{
for (int i = 0; i < 4; i++)
{
if (i == 0)
{
sem_init(sems + i, 0, 1);
}
else
{
sem_init(sems + i, 0, 0);
}
}
}
int main(int argc, char const *argv[])
{
int ret;
int num[4] = {0, 1, 2, 3};
open_file();
init_sems();
signal(SIGINT, my_exit);
for (int i = 0; i < 4; i++)
{
ret = pthread_create(ids + i, NULL, write_data, (void *)(num + i));
if (ret < 0)
{
perror("pthread create error");
exit(1);
}
pthread_detach(ids[i]);
}
pause();
return 0;
}