精华内容
下载资源
问答
  • 2021-05-09 04:13:23

    首先,所有的系统调用都是原子性的。这句话来自TLPI:

    "All system calls are executed atomically. By this, we mean that the kernel guarantees that all of the steps in a system call are completed as a single operation, without being interrupted by another process of thread."

    太好了!于是当两个线程或进程在同一时间写同一文件时,我们可以肯定他们的数据不会交错插入。这使调用write(2)不需要互斥锁,而且还能保证原子性,因为内核已经帮我们做到那个了。

    但是还有一个问题,一般写文件时,你需要找到你想插入的具体的位置,然后再进行真正的写入操作。不幸的是,这会涉及到两个系统调用,lseek(2)和write(2).他们各自是原子性的,但是两个操作作为一个整体就不是原子性的。让我们来证明下:

    用下面的伪代码表示写文件的过程:

    lseek(fd,0,SEEK_END);// seek to the end of the file

    write(fd,"log message",len);// perform the write

    在多线程环境下,这种操作是不安全的。通过这两个系统调用不能保证原子性,例如下面的情况:

    d'oh 线程A不在指向文件的真正末尾位置,它指向文件先前的默认位置,线程B写入信息的位置。当线程A写入文件时,可能被线程B写入的信息覆盖。

    通过这种方法写文件,有可能会丢失数据。

    但是还有一种方法。

    为了能保证seek和write两个操作发生的原子性,你可以设置O_APPEND标志,当你在打开一个文件时。然后,任何往文件追加的写操作都能保证是原子性的。这正是我们在写要共享日志文件时想要的情况。Logger和MonoLogger都是用这个标志来打开文件。

    open(filename,(FILE::WRONLY|FILE::APPEND))

    因此MonoLogger可以原子性的追加到日志系统,而不需要互斥信号。

    更多相关内容
  • 主要为大家详细介绍了java两个线程同时写一个文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • java多线程读写同一个文件

    千次阅读 2021-02-12 10:51:57
    本文提供java多线程分别定时读写同一个文件的样例,其中两线程,一个每分钟写入当前时间到指定文件,另一个线程读出每分钟新的内容。使用简单的Thread.sleep技术实现定时package test.thread;import java.io....

    本文提供java多线程分别定时读写同一个文件的样例,其中两个线程,一个每分钟写入当前时间到指定文件,另一个线程读出每分钟新写的内容。

    使用简单的Thread.sleep技术实现定时

    package test.thread;

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.FileReader;

    import java.io.FileWriter;

    import java.util.Date;

    /**

    * 多线程读写同一个文件的样例。

    */

    public class ThreadReadWrite {

    public static void main(String[] args) {

    new ThreadWrite().start();

    try {

    Thread.sleep(2000); // 休眠,以免那面还有写好

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    new ThreadRead().start();

    }

    }

    class ThreadWrite extends Thread {

    File file = new File("test.txt");

    @Override

    public void run() {

    try {

    while (true) {

    FileWriter out = new FileWriter(file, true);// 追加写入

    out.write(new Date() + "/n");

    out.flush();

    out.close();

    Thread.sleep(3000); // 我这里间隔改成3秒,方便测试

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    class ThreadRead extends Thread {

    File file = new File("test.txt");

    @Override

    public void run() {

    try {

    BufferedReader reader = new BufferedReader(new FileReader(file));

    while (true) {

    System.out.println(reader.readLine());

    Thread.sleep(3000); // 我这里间隔改成3秒,方便测试

    }

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    }

    如果真的要求严格,应该用Timer继续比较精确的控制。

    package test.thread;

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.FileReader;

    import java.io.FileWriter;

    import java.io.IOException;

    import java.util.Date;

    import java.util.Timer;

    import java.util.TimerTask;

    /**

    * 使用Timer定时器进行同一文件的读写。

    */

    public class ThreadReadWriteTimer {

    static File file = new File("test.txt");

    public static void main(String[] args) {

    Timer timer = new Timer();

    timer.scheduleAtFixedRate(new TimerTask() {

    @Override

    public void run() {

    FileWriter out;

    try {

    out = new FileWriter(file, true);

    // 追加写入

    out.write(new Date() + "/n");

    out.flush();

    out.close();

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }, 0, 3000);

    timer.scheduleAtFixedRate(new TimerTask() {

    BufferedReader reader = null;

    {

    try {

    reader = new BufferedReader(new FileReader(file));

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    @Override

    public void run() {

    try {

    System.out.println(reader.readLine());

    } catch (IOException e) {

    e.printStackTrace();

    }

    }

    }, 1000, 3000);

    }

    }

    2013年3月06日 14:24

    c4b32610104e4aa0a99ec1cf83cb32ab.gif

    13

    0

    0

    8

    展开全文
  • 主要为大家详细介绍了java多线程有序读取同一个文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了C#实现多线程写入同一个文件的方法,涉及C#多线程操作文件读写的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
  • 主要为大家详细介绍了python多线程同步之文件读写控制,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 采用C语言, 多线程同一个文件进行操作; * 2.每线程有自己的写入位置; * 3.每线程有自己的数据缓冲区; * 4.写文件前, 会 加锁(全局变量), 然后 将文件句柄 跳跃到指定位置, 下线程缓冲区的数据;...
  • java 多个线程同时写同一个文件

    千次阅读 2019-10-11 17:00:17
    话不说,先直接上代码: 主方法: import java.util.concurrent.CountDownLatch; /** * @ProjectName: emp_customer * @Package: PACKAGE_NAME * @ClassName: Test * @Author: Administrator * @...

    话不多说,先直接上代码:

    主方法:

    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: Test
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 14:10
     * @Version: 1.0
     */
    public class Test {
         public static void main(String args[]){
    
             //线程数
             int threadSize=4;
             //源文件地址
             String sourcePath = "E:\\1\\4.txt";
             //目标文件地址
             String destnationPath = "E:\\2\\4.txt";
             //
             CountDownLatch latch = new CountDownLatch(threadSize);
             MultiDownloadFileThread m = new MultiDownloadFileThread(threadSize, sourcePath, destnationPath, latch);
             long startTime = System.currentTimeMillis();
             try {
                 m.excute();
                 latch.await();
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
             long endTime = System.currentTimeMillis();
             System.out.println("全部下载结束,共耗时" + (endTime - startTime) / 1000 + "s");
         }
    
    }
    

     

    线程类:

    import java.io.*;
    import java.nio.channels.FileChannel;
    import java.nio.channels.FileLock;
    import java.util.concurrent.CountDownLatch;
    
    /**
     * @ProjectName: emp_customer
     * @Package: PACKAGE_NAME
     * @ClassName: MultiDownloadFileThread
     * @Author: Administrator
     * @Description: ${description}
     * @Date: 2019/10/11 15:03
     * @Version: 1.0
     */
    public class MultiDownloadFileThread {
    
        private int threadCount;
        private String sourcePath;
        private String targetPath;
        private CountDownLatch latch;
    
        public MultiDownloadFileThread(int threadCount, String sourcePath, String targetPath, CountDownLatch latch) {
            this.threadCount = threadCount;
            this.sourcePath = sourcePath;
            this.targetPath = targetPath;
            this.latch = latch;
        }
    
        public void excute() {
            File file = new File(sourcePath);
            int fileLength = (int) file.length();
            //分割文件
            int blockSize = fileLength / threadCount;
            for (int i = 1; i <= threadCount; i++) {
                //第一个线程下载的开始位置
                int startIndex = (i - 1) * blockSize;
                int endIndex = startIndex + blockSize - 1;
                if (i == threadCount) {
                    //最后一个线程下载的长度稍微长一点
                    endIndex = fileLength;
                }
                System.out.println("线程" + i + "下载:" + startIndex + "字节~" + endIndex + "字节");
                new DownLoadThread(i, startIndex, endIndex).start();
            }
        }
    
    
        public class DownLoadThread extends Thread {
            private int i;
            private int startIndex;
            private int endIndex;
    
            public DownLoadThread(int i, int startIndex, int endIndex) {
                this.i = i;
                this.startIndex = startIndex;
                this.endIndex = endIndex;
            }
    
            @Override
            public void run() {
                File file = new File(sourcePath);
                FileInputStream in = null;
                RandomAccessFile raFile = null;
                FileChannel fcin = null;
                FileLock flin = null;
                try {
                    in = new FileInputStream(file);
                    in.skip(startIndex);
                    //给要写的文件加锁
                    raFile = new RandomAccessFile(targetPath, "rwd");
                    fcin =raFile.getChannel();
                    while(true){
                        try {
                            flin = fcin.tryLock();
                            break;
                        } catch (Exception e) {
                            System.out.println("有其他线程正在操作该文件,当前线程休眠1000毫秒,当前进入的线程为:"+i);
                            sleep(1000);
                        }
                    }
                    //随机写文件的时候从哪个位置开始写
                    raFile.seek(startIndex);
                    int len = 0;
                    byte[] arr = new byte[1024];
                    //获取文件片段长度
                    int segLength = endIndex - startIndex + 1;
                    while ((len = in.read(arr)) != -1) {
                        if (segLength > len) {
                            segLength = segLength - len;
                            raFile.write(arr, 0, len);
                        } else {
                            raFile.write(arr, 0, segLength);
                            break;
                        }
                    }
                    System.out.println("线程" + i + "下载完毕");
                    //计数值减一
                    latch.countDown();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException | InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (in != null) {
                            in.close();
                        }
                        if (raFile != null) {
                            raFile.close();
                        }
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    运行结果:

     

    涉及到的相关知识点:

    1.CountDownLatch 

    2.RandomAccessFile

    3.FileLock

    下面我们具体讲解下

    一、FileLock :文件锁

    FileLock是java 1.4 版本后出现的一个类,它可以通过对一个可写文件(w)加锁,保证同时只有一个进程可以拿到文件的锁,这个进程从而可以对文件做访问;而其它拿不到锁的进程要么选择被挂起等待,要么选择去做一些其它的事情, 这样的机制保证了众进程可以顺序访问该文件。

    1. 概念

    • 共享锁: 共享读操作,但只能一个写(读可以同时,但写不能)。共享锁防止其他正在运行的程序获得重复的独占锁,但是允许他们获得重复的共享锁。
    • 独占锁: 只有一个读或一个写(读和写都不能同时)。独占锁防止其他程序获得任何类型的锁。

    2. lock()和tryLock()的区别:

    lock()阻塞的方法,锁定范围可以随着文件的增大而增加。无参lock()默认为独占锁;有参lock(0L, Long.MAX_VALUE, true)为共享锁。
    tryLock()非阻塞,当未获得锁时,返回null.
    3. FileLock的生命周期:在调用FileLock.release(),或者Channel.close(),或者JVM关闭

    4. FileLock是线程安全的
     

    二、RandomAccessFile

    java除了File类之外,还提供了专门处理文件的类,即RandomAccessFile(随机访问文件)类。该类是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,这里“随机”是指可以跳转到文件的任意位置处读写数据。在访问一个文件的时候,不必把文件从头读到尾,而是希望像访问一个数据库一样“随心所欲”地访问一个文件的某个部分,这时使用RandomAccessFile类就是最佳选择。

    RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当前读写n个字节后,文件指示器将指向这n个字节后面的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。RandomAccessFile类在数据等长记录格式文件的随机(相对顺序而言)读取时有很大的优势,但该类仅限于操作文件,不能访问其他的I/O设备,如网络、内存映像等。RandomAccessFile类的构造方法如下所示:

    RandomAccessFile(File file ,  String mode)
    //创建随机存储文件流,文件属性由参数File对象指定

    RandomAccessFile(String name ,  String mode)
    //创建随机存储文件流,文件名由参数name指定

    这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:

    “r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
    “rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
    “rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
    “rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作

     

    三、CountDownLatch

    1.概念

    • countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行。
    • 是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。

    2.源码

    • countDownLatch类中只提供了一个构造器:
    //参数count为计数值
    public CountDownLatch(int count) {  };  
    
    • 类中有三个方法是最重要的:
    //调用await()方法的线程会被挂起,它会等待直到count值为0才继续执行
    public void await() throws InterruptedException { };   
    //和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
    public boolean await(long timeout, TimeUnit unit) throws InterruptedException { };  
    //将count值减1
    public void countDown() { };  

    假如在我们的代码里面,我们把main方法里面的

    latch.await();

    注释掉

    如下所示:

    我们可以看到跟之前的输出结果相比,我们的主方法里面输出的:全部下载结束的输出信息,已经打印到我们执行文件下载的线程输出信息的前面了,说明主线程先执行完。这从而说明,await() 方法具有阻塞作用

     我们在把latch.await();放开,把文件下载线程里的latch.countDown();注释掉,

    如下:

    我们可以看到,主程序里的的输出;全部下载结束的输出信息,一直未输出,程序也一直未结束,由此可得,countDown() 方法具有唤醒阻塞线程的作用。

    那么如何让 CountdownLatch 尽早结束

    假如我们的程序执行到countDown()之前就抛出异常,这就可能导致一整情况,CountdownLatch 计数永远不会达到零并且 await() 永远不会终止。

    为了解决这个问题,我们在调用 await() 时添加一个超时参数。

     

    CountDownLatch总结:

        1、CountDownLatch end = new CountDownLatch(N); //构造对象时候 需要传入参数N

      2、end.await()  能够阻塞线程 直到调用N次end.countDown() 方法才释放线程,最好设置超时参数

      3、end.countDown() 可以在多个线程中调用  计算调用次数是所有线程调用次数的总和

     

    对于,本demo而言,加不加文件锁的意义不大,因为在进入线程写的时候,就已经告诉单个线程需要写的内容是哪一块到哪一块,不加锁,也会正常写入,切经本人测试无误,但若是对同一个文件,即要写,又要读话,就必须加锁,不然程序执行可能不完整,具体情况可以查看下面的这个博客:https://blog.csdn.net/gxy3509394/article/details/7435993

    展开全文
  • class Program { #region 私有字段 // 文件名 static readonly string FileName = "demoFile.... // 要写入文件的 9 字节 static readonly byte[] orgBuffer = { 0x0C, 0x10, 0x02, 0xE3, 0x71, 0xA2, ...
    class Program
    {
       #region 私有字段
       // 文件名
       static readonly string FileName = "demoFile.data";
       // 要写入文件的 9 个字节
       static readonly byte[] orgBuffer =
       {
           0x0C, 0x10, 0x02,
           0xE3, 0x71, 0xA2,
           0x13, 0xB8, 0x06
       };
    
       // 相关的信号事件
       static AutoResetEvent[] writtenEvents = {
           new AutoResetEvent(false),
           new AutoResetEvent(false),
           new AutoResetEvent(false)
       };
       #endregion
    
       static void Main(string[] args)
       {
           if (File.Exists(FileName))
               File.Delete(FileName);
    
           // 启动三个线程写文件
           for (int n = 0; n < 3; n++)
           {
               Thread th = new Thread((p) =>
               {
                   // 先把要写的字节复制出来
                   int currentCount = Convert.ToInt32(p);
                   int copyIndex = currentCount * 3;
                   byte[] tmpBuffer = new byte[3];
                   Array.Copy(orgBuffer, copyIndex, tmpBuffer, 0, 3);
                   // 打开文件流
                   using (FileStream fs = new FileStream(FileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write))
                   {
                       // 定位流的当前位置
                       fs.Seek(copyIndex, SeekOrigin.Begin);
                       // 写入数据
                       fs.Write(tmpBuffer, 0, tmpBuffer.Length);
                   }
                   // 发出信号
                   writtenEvents[currentCount].Set();
               });
               // 标识为后台线程
               th.IsBackground = true;
               // 启动线程
               th.Start(n);
           }
    
           Console.WriteLine($"原始字节序列:\n{BitConverter.ToString(orgBuffer)}");
           Console.WriteLine("等待所有线程完成文件写入……");
           WaitHandle.WaitAll(writtenEvents);
           Console.WriteLine("文件写入完成。");
           // 把文件内容读出来
           using (FileStream fsin = new FileStream(FileName, FileMode.Open))
           {
               byte[] buffer = new byte[fsin.Length];
               fsin.Read(buffer, 0, buffer.Length);
               Console.WriteLine($"从文件读出来的字节:\n{BitConverter.ToString(buffer)}");
           }
    
           Console.Read();
       }
    }
    
    展开全文
  • c++ 多线程同一个文本写入信息 解决同步与互斥问题
  • Java 多线程写同一个文件实现

    万次阅读 2013-05-07 17:06:14
    最近项目中需要从网站上抓取大量的数据,采用了多线程技术,每线程抓取的数据都需要保存到一个文件中,避免消耗大量的内存。 思路:多访问线程将需要写入到文件中的数据先保存到一个队列里面,然后由专门的 ...
  • 下面的案例证明了文件读取操作和文件写出操作可以同时进行,文件写出和文件写出也可以同时进行 package com.sun.redis; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; ...
  • C# 多线程按多文件名写文件源码,以及调用示例,供初学者学习用
  • 具体实现思路就举列子说明吧: 假设有10000字节需要写入某个文件,为了加快写入速度,可以开启2个线程,第一个线程将前5000字节写入文件0~4999的位置,另外一个线程将后5000字节写入文件5000~9999的位置,等...
  • Python 多线程文件io

    千次阅读 2021-01-13 20:04:46
    import os #目录操作def writeFile():fo = open("foo.txt", "a+") #打开一个文件,第二参数为打开的模式:r 只读,r+读写 w只 w+读写 wb二进制方式只 a 追加print ("文件名: ", fo.name)print("是否已关闭 : ...
  • java多线程同时读取一个文件

    千次阅读 2021-03-17 23:45:12
    import java.io.*;class DownThread extends Thread {//定义字节数组(取水的竹筒)的长度private final int BUFF_LEN = 32;//定义读取的起始点...//读取文件对应的输入流private InputStream is;//将读取到的字节...
  • 假如A、B、C三线程同时对同一个test.txt文本文档进行操作,这时候如果没有进行锁的操作,那么就会出现错误提示文件正在被操作。 【多线程锁解决】 支持单个线程和多读线程的锁,.net 3.5> 可定义在...
  • 多线程写文件

    2014-12-19 11:49:17
    有四个线程,A线程负责“A”,B线程负责“B”,C线程负责“C”,D线程负责“D”。分别有四个文件,A文件的内容:“ABCD ABCD...”,B文件的内容:“BCD ABCD A...”,C文件的内容:“CD ABCD AB...”,D文件...
  • 三、java8htmljava多线程同时写一个文件java高并发环境下多线程同时写入一个文件时,经过 FileLock 加锁,能够控制对文件的并发操做。同一个JVM,能够共享部份内存java第种状况是:一个线程A有对文件加锁,另外...
  • 本文介绍种在PHP中解决多进程或多线程同时读写同一个文件的问题。
  • 多线程一个文件数据

    万次阅读 2017-09-04 10:43:04
    最近被问到Log4j如何通过多个线程一个文件中写入数据,当时没有一点头绪, 因为用过windows记事本的小伙伴都知道,当一个记事本文件被同时打开次,并且每都修改,那么只会保留第次打开的内容,这就是互斥锁...
  • 多线程写同一个文件

    2018-09-10 20:53:43
    多线程写同一个文件,不阻塞,可以延迟一下稍后再写。 怎么处理好? 谢谢。
  • 1.多线程 线程是程序执行流的最小单元。是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的...
  • 多线程写同一个excel文件(导出)

    千次阅读 2018-03-22 15:14:17
    最近一个excel导出的任务让我搞了好久,想想踩过的坑,就想上来小结一番。 ------------------------------------------------------分割线------------------------------------------------------   ...
  • 个线程会自动在运行目录下出当前题目计算结果,实现实时保存。 可以直接使用几百或者上千个线程(本机使用的是1000个线程) 题目并且线程多的情况下,会出现线程已经执行完成,但是列表框还没在显示。
  • 知识目录 &amp;amp;lt;?php $fp = fopen(&amp;quot;/tmp/lock.txt&amp;quot;, &amp;quot;w+&amp;quot;); if(flock($fp, LOCK_EX)){ // 进行排它型锁定 ... flock($fp, LOCK_U
  • LINUX多线程读写同一个文件 加锁

    千次阅读 2014-05-07 18:30:28
    当有多个工作线程要同时对一个文件进行操作时,如果不对该文件进行加锁就可能会因误操作而引起系列的问题。  解决这问题有多种方法。我们这里考虑使用文件锁来对文件进行保护,因为这方法简单易行。具体...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,226,935
精华内容 490,774
关键字:

多线程写同一个文件