LinuxC 线程 -- 信号量

互斥信号量代码如下:

#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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值