利用多线程完成图片复制,主线程复制前一半,子线程复制后一半;多线程翻转字符串与输出字符串

一、俩demo

1.1 多线程完成图片复制

  • 利用多线程完成图片复制,主线程复制前一半,子线程复制后一半
  • 这个在之前多进程复制时已经有了相对完备的思想了,所以就不介绍具体思路了,差不多的思路

1.2 多线程翻转字符串与输出字符串

要求如下:

  • 定义一个全局变量 char buf[] = “1234567”,创建两个线程,不考虑退出条件。
    1. A线程循环打印buf字符串,
    2. B线程循环倒置buf字符串,即buf中本来存储1234567,倒置后buf中存储7654321. B线程中不打印!!
    3. 倒置不允许使用辅助数组。
    4. 要求A线程打印出来的结果只能为 1234567 或者 7654321 不允许出现7634521 7234567
    5. 不允许使用sleep函数

思路:

  • 一开始就想着用标志信号的方式完成,标志信号是通过 pthread_create 函数中的参数传到子进程的
  • 主线程中循环打印字符串
  • 子线程中循环将字符串翻转
  • 下边是实现的思路
  • 标志信号初始值我设定的为 0
  • 打印时检查标志信号是否为 0,若为 0 则进行打印,打印完再将标志信号更改为 1 ,等待翻转时进行使用
  • 翻转时检查标志信号是否为 1 ,若为 1 则进行翻转,翻转完再将标志信号改为 0 ,等待打印时使用
  • 这种检查完标志信号是否符合再进行操作,操作完再进行修改标志信号,能够在一定程度上保证操作的原子性(即不可分割性)

二、多线程图片复制的代码

#include <my_head.h>

/*
利用线程复制图片,主线程复制前一半,子线程复制后一半
*/

void *half_copy(void *offset);

int main(int argc, const char *argv[])
{
    //  修改文件掩码,并创建复制后的目的文件,若存在则清空,不存在则创建
    umask(0);
    int dest = open("copy.png", O_WRONLY | O_CREAT | O_TRUNC, 0664);
    close(dest);

    //  打开两个文件,读源文件,写目的文件
    int src1 = open("1.png", O_RDONLY);
    int dest1 = open("copy.png", O_WRONLY);

    //  获取源文件的一半偏移量
    off_t offset = lseek(src1, 0, SEEK_END);
    offset /= 2;
    //  再将偏移量移回文件开头
    lseek(src1, 0, SEEK_SET);

    // printf("主线程offset = %ld\n", offset);
    //  创建子线程,子线程号为tid
    pthread_t tid;
    if (0 != pthread_create(&tid, NULL, half_copy, &offset))
    {
        fprintf(stderr, "pthread_create error  __%d__\n", __LINE__);
        return -1;
    }
    //  创建用于过度的存储变量
    char temp[128];
    //  接收读取的字节数返回值
    ssize_t res;
    while (1)
    {
        //  清空过度存储变量
        bzero(temp, sizeof(temp));
        //  判断剩余偏移量是否比过度存储容量大
        //  若大于等于过度存储容量,则用过度存储容量的大小进行读取写入
        //  若小于,则用剩余偏移量的大小进行读取写入
        if (offset >= sizeof(temp))
        {
            res = read(src1, temp, sizeof(temp));
            //  成功读取则写入,否则结束循环
            if (0 < res)
            {
                write(dest1, temp, res);
            }
            //  没读到数据但成功执行读取函数则退出
            else if (0 == res)
            {
                //  输出提示
                printf("主线程中----图片复制完成\n");
                break;
            }
            //  执行读取函数失败则返回NULL
            else
            {
                ERR_MSG("read file error");
                return -1;
            }
        }
        else
        {
            printf("主线程读取到达边缘\n");
            res = read(src1, temp, offset);
            //  读到数据就进行写入
            if (0 < res)
            {
                write(dest1, temp, res);
            }
            //  没读到数据但成功执行读取函数则退出
            else if (0 == res)
            {
                //  输出提示
                printf("主线程中----图片复制完成\n");
                break;
            }
            //  执行读取函数失败则返回NULL
            else
            {
                ERR_MSG("read file error");
                return -1;
            }
        }
        //  修改偏移量
        offset -= sizeof(temp);
    }

    //  释放两个文件IO函数
    close(src1);
    close(dest1);

    //  等待子线程结束
    pthread_join(tid, NULL);

    //  输出提示
    printf("图片复制完成\n");
    return 0;
}

void *half_copy(void *half_offset)
{
    //  检查传进来的偏移量
    // printf("子线程half_offset = %ld\n", *(off_t *)half_offset);
    //  偏移量,偏移一半
    off_t offset = *(off_t *)half_offset;

    //  打开两个文件,读源文件,写目的文件
    int src2 = open("1.png", O_RDONLY);
    int dest2 = open("copy.png", O_WRONLY);

    //  将源文件和目的文件向后偏移一半
    lseek(src2, offset, SEEK_SET);
    lseek(dest2, offset, SEEK_SET);

    //  用于接收读取的字节数返回值
    ssize_t res;
    //  创建用于过度的存储变量
    char temp[256];
    while (1)
    {
        //  复制后半部分就不用担心读取越界了
        //  因为读到最后若过度存储容量没占满,那么有多少读多少
        res = read(src2, temp, sizeof(temp));
        //  读到数据就进行写入
        if (0 < res)
        {
            write(dest2, temp, res);
        }
        //  没读到数据但成功执行读取函数则退出
        else if (0 == res)
        {
            //  输出提示
            printf("子线程中----图片复制完成\n");
            break;
        }
        //  执行读取函数失败则返回NULL
        else
        {
            ERR_MSG("read file error");
            return NULL;
        }
    }

    //  释放两个文件IO函数
    close(src2);
    close(dest2);
    //  结束子线程
    pthread_exit(NULL);
}

三、多线程翻转输出字符串代码

#include <my_head.h>

//  用于翻转的字符串
char str[8] = "1234567";

void *turn_str(void *flag);

int main(int argc, const char *argv[])
{
    //  标志信号
    int flag = 0;
    //  创建子线程,子线程号为tid
    pthread_t tid;

    if (pthread_create(&tid, NULL, turn_str, (void *)&flag) != 0)
    {
        fprintf(stderr, "pthread_create error    __%d__\n", __LINE__);
        return -1;
    }

    //  暂定打印90次,太多不容易看,打太快了
    int i = 0;
    while (i < 90)
    {
        //  当标志信号为0时输出字符串,输出完再将标志信号换成1
        if (flag == 0)
        {
            printf("%s\n", str);
            i++;
            //  改变标志信号
            flag = 1;
        }
    }

    return 0;
}
//  翻转
void *turn_str(void *flag)
{
    int len = strlen(str);
    while (1)
    {
        //  当标志信号为1时进行翻转,翻转后再将标志信号换成0
        if (*(int *)flag == 1)
        {
            char *s = str, *s1 = str + len - 1;
            //  翻转
            while (s < s1)
            {
                (*s) ^= (*s1);
                (*s1) ^= (*s);
                (*s) ^= (*s1);
                s++;
                s1--;
            }
            //  改变标志信号
            *(int *)flag = 0;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhk___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值