Java逐行读取文件有多少种方法?

如果每个线程使用的变量都是其它线程不会读取或修改的,那么就不存在一致性问题。同样,如果变量是只读的,多个线程同时读取该变量也不会有一致性问题。否则,将会出现不一致性问题。为了解决数据不一致问题,必须引入某些机制使线程间同步。

当变量修改时间多于一个存储器访问周期,同时读、写操作又相互交替时,潜在的不一致性就会出现。如下图所示:

此时,线程B读取到的数据是错误的。使用一把锁能够解决上述问题:

下面介绍线程的三种同步机制:

1、互斥量pthread_mutex_t

互斥量就是锁,对某段临界区进行加锁,使得线程只能串行访问这段临界区。对互斥量进行加锁后,任何其它试图再次对互斥量加锁的线程将会被阻塞直到当前线程释放该互斥量。

2、读写锁pthread_rwlock_t

与互斥量类似,但并行性更高。读写锁有三种状态:

  • 读模式加锁状态
  • 写模式加锁状态
  • 不加锁状态

一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。下面是读写锁的逻辑关系表:

锁状态\需要加的锁 读模式加锁 写模式加锁
读模式 允许 阻塞直到所有线程释放读锁
写模式 阻塞直到写锁被释放 阻塞直到写锁被释放
不加锁 允许 允许

3、条件变量pthread_cond_t

条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生。条件变量(由用户自由定义)本身受互斥量保护,对条件的修改都必须先加锁。

这里要注意条件和条件变量之间的区别。条件变量是由系统提供的结构体pthread_cond_t,它用来在多个线程间传递信号;而条件则由用户代码定义,用于多个线程间共享某些数据。

测试代码:

#include <stdio.h>
#include <pthread.h>

/* 自定义的条件 */
struct msg {
    struct msg *m_next;
    char *data;
};

struct msg *workq;    /* 定义一个消息队列 */
pthread_cond_t qready = PTHREAD_COND_INITIALIZER;    /* 静态分配条件变量 */
pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;   /* 静态分配互斥量 */

void process_msg(void)
{
    struct msg *mp;

    while (1)
    {
        pthread_mutex_lock(&qlock);
        while (workq == NULL)
        {
            /* 此函数把线程放到等待条件的线程列表上,然后对互斥量解锁
             * 函数返回时,互斥量再次被锁住
             */
            pthread_cond_wait(&qready, &qlock);
        }

        /* 从消息队列头取出一个消息 */
        mp = workq;
        workq = workq->m_next;
        pthread_mutex_unlock(&qlock);

        printf("%s\n", mp->data);   /* 打印收到的消息 */
    }
}

void enqueue_msg(struct msg *mp)
{
    pthread_mutex_lock(&qlock);
    mp->m_next = workq;                /* 新消息放队列头部 */
    workq = mp;
    pthread_mutex_unlock(&qlock);
    pthread_cond_signal(&qready);   /* 唤醒等待该条件的某个线程 */
}

void *thr_fn1(void *arg)
{
    process_msg();
}

void *thr_fn2(void *arg)
{
    struct msg msg1, msg2, msg3;

    msg1.data = "Hello world";
    msg2.data = "I love you";
    msg3.data = "This is a test!";

    /* 将消息放入队列 */
    enqueue_msg(&msg1);
    enqueue_msg(&msg2);
    enqueue_msg(&msg3);
}

int main(void)
{
    pthread_t tid1, tid2;

    pthread_create(&tid1, NULL, thr_fn1, NULL);
    pthread_create(&tid2, NULL, thr_fn2, NULL);

    pthread_join(tid1, NULL);

    return 0;
}

运行结果:

可以看到两个线程成功进行了数据传递。

这里要注意pthread_cond_wait函数的用法。

函数原型:pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)

函数传入的参数mutex用于保护条件,因为我们在调用pthread_cond_wait时,如果条件不成立就进入阻塞,但是进入阻塞这个期间,如果条件变量改变了的话,那我们就漏掉了这个条件。因为这个线程还没有放到等待队列上,所以调用pthread_cond_wait前要先锁互斥量,即调用pthread_mutex_lock(),pthread_cond_wait在把线程放进阻塞队列后,自动对mutex进行解锁,使得其它线程可以获得加锁的权利。这样其它线程才能对临界资源进行访问并在适当的时候唤醒这个阻塞的进程。当该函数返回后又自动给mutex加锁。

下面说明如何避免死锁。一般在下列情况下会出现死锁:

  • 线程试图对同一个互斥量加锁两次
  • 已拥有各自互斥量的两个线程相互请求加锁对方的互斥量

以下方法可以避免死锁的发生:

  • 假设需要对两个互斥量同时加锁,那么要求所有线程必须先加锁A(或B),再加锁B(或A),死锁就不会发生。只有在一个线程试图以另一个线程相反的顺序锁住互斥量时,才可能出现死锁。
  • 使用pthread_mutex_trylock函数,如果不能获得锁,先释放已经拥有的锁,过段时间重新尝试。

参考:

《unix环境高级编程》 P297-P311.

Java逐行读取文件有多少种方法?,布布扣,bubuko.com

时间: 2024-08-13 13:54:40

Java逐行读取文件有多少种方法?的相关文章

Java:逐行读取文件的用法

import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.List; public class HelloWord { public static void main(Stri

python 逐行读取文件的几种方法

Python四种逐行读取文件内容的方法 下面四种Python逐行读取文件内容的方法, 分析了各种方法的优缺点及应用场景,以下代码在python3中测试通过, python2中运行部分代码已注释,稍加修改即可. 方法一:readline函数 # -*- coding: UTF-8 -*- f = open("/pythontab/code.txt") # 返回一个文件对象 line = f.readline() # 调用文件的 readline()方法 while line: # pri

java解析xml文件四种方式介绍、性能比较和基本使用方法

一.介绍: 1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息.分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作.由于它是基于信息层次的,因而DOM被认为是基于树或基于对象的.DOM以及广义的基于树的处理具有几个优点.首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改.它还可以在任何时候在树中上下导航,而不

Linux中逐行读取文件的方法

  Linux中逐行读取文件的方法             在linux中有很多方法逐行读取一个文件的方法,其中最常用的就是下面的脚本里的方法,而且是效率最高,使用最多的方法.为了给大家一个直观的感受,我们将通过生成一个大的文件的方式来检验各种方法的执行效率. 方法1:while循环中执行效率最高,最常用的方法. function while_read_LINE_bottm(){ While read LINE do echo $LINE done   < $FILENAME } 注释:我习惯把

Linux shell逐行读取文件的方法

Linux shell逐行读取文件的方法 在Linux中有很多方法逐行读取一个文件的方法,其中最常用的就是下面的脚本里的方法,而且是效率最高,使用最多的方法.为了给大家一个直观的感受,我们将通过生成一个大的文件的方式来检验各种方法的执行效率. 方法1:while循环中执行效率最高,最常用的方法. function while_read_LINE_bottm(){ While read LINE doecho $LINEdone  < $FILENAME}         注释:我习惯把这种方式叫

java解析xml的三种方法

java解析XML的三种方法 1.SAX事件解析 package com.wzh.sax; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; // public class Saxhandler extends DefaultHandler { @Override public void startDocument() throws

详解Java解析XML的四种方法

(1)DOM解析 DOM是html和xml的应用程序接口(API),以层次结构(类似于树型)来组织节点和信息片段,映射XML文档的结构,允许获取 和操作文档的任意部分,是W3C的官方标准 [优点] ①允许应用程序对数据和结构做出更改. ②访问是双向的,可以在任何时候在树中上下导航,获取和操作任意部分的数据. [缺点] ①通常需要加载整个XML文档来构造层次结构,消耗资源大. [解析详解] ①构建Document对象: DocumentBuilderFactory dbf = DocumentBu

python逐行读取文件脚本

逐行读取的方法很多,这里提供一种非常简单的方法: #!/usr/bin/python # -*- coding: utf-8 -*- for line in open("awip.conf"): print line 其他的可以参考教程:python逐行读取文件内容的三种方法Python--文件读取 原文地址:http://blog.51cto.com/weiruoyu/2140927

[转]Java实现定时任务的三种方法

在应用里经常都有用到在后台跑定时任务的需求.举个例子,比如需要在服务后台跑一个定时任务来进行非实时计算,清除临时数据.文件等.在本文里,我会给大家介绍3种不同的实现方法: 普通thread实现 TimerTask实现 ScheduledExecutorService实现 普通thread 这是最常见的,创建一个thread,然后让它在while循环里一直运行着,通过sleep方法来达到定时任务的效果.这样可以快速简单的实现,代码如下: public class Task1 { public st