`
做一行爱一行吧
  • 浏览: 23638 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java的线程读写操作(共享和互斥)

    博客分类:
  • java
 
阅读更多

       最近看了看java的线程操作的方法的内容,照书上写了一下代码试了试,主要的内容是我们固定输入一段字符串,然后依次按顺序读每一个字符,创建6个读操作的线程和2个写进程的进程,操作的方式是,可以同时读,但是不可以同时写,而且在读的时候不可以写,写的时候不可以读!

      erlang多是利用同步异步消息来处理数据问题,所以有的时候自己经常会忘记锁了以后要解锁!!!!

      

package test1;

public class Main {
	public static void main(String[] args){
		Data data = new Data(10);		//创建Data类的实例
		/**启动6个读操作线程**/
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		new ReaderThread(data).start();
		/**启动2个写操作线程**/
		new WriterThread(data, "ABCDEFGHIJKLMNOPQRSTUVWXYZ").start();
		new WriterThread(data, "abcdefghijklmnopqrstuvwxyz").start();
	}
}

 

package test1;

/**数据操作类**/
public class Data {
		private final char[] buffer;	//新建一个缓存字符串数组
		private final ReadWriteLock lock = new ReadWriteLock();		//创建一个ReadWriteLock类的对象lock
		
		/**Data类的构造函数,输入一个size**/
		public Data(int size){	
			this.buffer = new char[size];	//为buffer对象申请size大小的空间
			for(int i = 0; i < buffer.length; i++){
				buffer[i] = '*';			//将buffer内初始为*号
			}
		}
		
		/**读操作方法(主要完成的是锁操作)**/
		public char[] read() throws InterruptedException{
			lock.readLock();	//对lock实例进行读锁操作
			try{
				return doRead();	//读操作
			}finally{
				lock.readUnlock();	//对lock实例读解锁操作
			}
		}
		
		/**写操作方法(主要完成的是锁操作)**/
		public void write(char c) throws InterruptedException{
			lock.writeLock();	//对lock实例进行写锁操作
			try{
				doWrite(c);		//进行写操作
			}finally{
				lock.writeUnlock();	//进行写解锁
			}
		}
		
		/**读操作主要逻辑**/
		private char[] doRead(){
			char[] newbuf = new char[buffer.length];	//创建一个大小为buffer.length的newbuf对象
			for(int i = 0; i < buffer.length; i++){
				newbuf[i] = buffer[i];					//数据拷贝
			}
			slowly();									//延迟操作
			return newbuf;								//返回newbuf
		}
		
		/**写操作主要逻辑**/
		private void doWrite(char c){
			for(int i = 0; i < buffer.length; i++){
				buffer[i] = c;							//将buffer中的数据替换成字符串c
				slowly();								//延迟操作
			}
		}
		
		/**模拟时间操作**/
		private void slowly(){
			try{
				Thread.sleep(0);						//延迟50毫秒
			}catch(InterruptedException e){
				
			}
		}
}

 

package test1;

/**读写锁操作类**/
public final class ReadWriteLock {
	private int readingReaders = 0;  //阅读者的数量
	private int waitingWriters = 0;   //等待的编辑者数量
	private int writingWriters = 0;   //编辑者的数量
	private boolean preferWriter = true;   //是否正在被编辑
	
	/**读锁**/
	public synchronized void readLock() throws InterruptedException{
		//如果是 编写者的数量大于0  并且 等待的编写者大于0或者正在被编写  那么该进程等待
		while(writingWriters > 0 || (preferWriter && waitingWriters >0)){
			//等待操作
			wait();
		}
		//读写者加1可以读
		readingReaders++;
	}
	
	/**读解锁**/
	public synchronized void readUnlock(){
		readingReaders--;	//读者减1 解锁读
		preferWriter = true;	//可以写
		notifyAll();	//唤醒其他进程操作
	}
	
	/**写锁**/
	public synchronized void writeLock() throws InterruptedException{
		waitingWriters++; //编辑者加1
		try{
			//如果读者大于0 并且 编写者大于0
			while(readingReaders > 0 || writingWriters > 0){
				//等待操作
				wait();
			}
		}finally{
			waitingWriters--;	//最终等待者减1
		}
		writingWriters++;	//编写者加1
	}
	
	/**编写者解锁**/
	public synchronized void writeUnlock(){
		writingWriters --;	//编辑者减1
		preferWriter = false;	//没有被编辑
		notifyAll();	//唤醒其他的进程
	}
}

 

package test1;
import java.util.Random;

/**写操作线程类**/
public class WriterThread extends Thread {
	private static final Random random = new Random();	//random的实例
	private final Data data;	//创建一个Data的实例
	private final String filler;	//创建一个filler的字符串
	private int index = 0;			//创建一个index类为0
	
	/**WriterThread类构造器**/
	public WriterThread(Data data, String filler){
		this.data = data;
		this.filler = filler;
	}
	
	/**启动线程实现run方法**/
	public void run(){
		try{
			while(true){
				char c = nextchar();	//返回filler中的下一个字符
				data.write(c);			//将字符c写入
				Thread.sleep(random.nextInt(3000));	//1~3000随机休眠
			}
		}catch (InterruptedException e){
			
		}
	}
	
	/**实现nextchar的方法,指定索引位置的char值**/
	private char nextchar(){
		char c = filler.charAt(index);	//字符串的位置
		index++;						//index的值递增
		if(index >= filler.length()){
			index = 0;					//如果index的值大于字符串的长度则index为0
		}
		return c;
	}
}

 

package test1;

/**读操作的线程类**/
public class ReaderThread extends Thread{
	private final Data data;

        这个程序虽然只是简单的多线程编程的一个例子,但是只要将main函数以及模拟休息的部分和输入的buffer参数稍作修改就可以完成一些真正意义上的并发锁的操作

 

       这里还是有些要注意的:

       1.你想要保护什么就锁什么!

       2.完成操作一定要解锁!

 

测试例子:(比较多,总之在读完所有的字符以前不出现混乱读取)

 

 

  • 大小: 1.1 KB
分享到:
评论

相关推荐

    操作系统中对于线程的同步与互斥问题的设计原理及代码

    操作系统中的线程同步与互斥是并发编程中的关键概念,它们确保了多线程环境下的程序正确性和资源安全。线程互斥是指当多个线程访问同一临界资源时,同一时刻只允许一个线程进行操作,以防止数据竞争和不一致的状态。...

    多线程编程和操作系统线程同步互斥演示

    在这个“多线程编程和操作系统线程同步互斥演示”中,作者可能创建了一个或多个人工场景,展示了如何在VC++环境中使用多线程,并且演示了线程同步和互斥的实践应用。这可能涉及到以下几个方面: 1. **线程创建**:...

    多线程通信读写文件

    互斥锁确保在任何时候只有一个线程能访问共享资源,而监视器(如Java中的`synchronized`关键字)则提供了更高层次的抽象,它不仅提供互斥,还允许线程等待其他线程释放资源。 在读取文件时,多线程可能带来性能提升...

    线程间互斥2

    6. **读写锁(ReadWriteLock)**:Java 中的 ReentrantReadWriteLock 允许多个线程同时读取共享资源,但在写操作时仍然保持互斥,这样可以提高系统的并发性能。 7. **死锁(Deadlock)**:当两个或更多的线程相互...

    线程进程互斥锁

    - **文件操作**:在多个线程或进程中,如果需要对同一个文件进行读写操作,使用互斥锁可以防止数据的混乱,确保每次只有一个线程或进程进行读写。 - **全局变量**:当多个线程需要修改全局变量时,互斥锁能确保...

    关于读写锁算法的Java实现及思考

    }`来避免读线程间的互斥,以及如何通过`wait`和`notifyAll`方法协调读写线程之间的同步。 ### 总结 读写锁是并发编程中一种重要的锁机制,尤其适用于读多写少的场景。在Java中,`ReentrantReadWriteLock`提供了...

    读写线程模仿

    在Java中,实现读写线程的同步通常有两种策略:互斥访问和读者-写者问题。"读者优先"的策略是一种解决读者-写者问题的方式,它允许同时有多个读者访问资源,但当有写者时,所有读写操作都必须暂停,直到写者完成其...

    Java多线程编程核心技术_完整版_java_

    1. synchronized关键字:用于保证线程安全,它可以修饰方法或代码块,实现对共享资源的互斥访问。 2. volatile关键字:保证变量的可见性和有序性,但不保证原子性。 3. Lock接口与ReentrantLock类:提供了比...

    一个多线程同步读写的小程序

    线程是操作系统分配处理器时间的基本单位,每个线程都有自己的程序计数器、栈和局部变量,但共享同一块内存空间。这意味着多个线程可以访问相同的资源,这在读写操作中可能引发问题,因为如果一个线程正在写入数据,...

    第20章 Part3 多线程互斥与协作.pdf

    ### 第20章 Part3:多线程互斥与协作 ...综上所述,互斥和协作是线程编程中的两个核心概念,对于编写高效稳定的多线程应用程序至关重要。通过正确理解和应用这些概念,开发者可以有效地避免竞态条件和其他并发问题。

    java 读写锁代码

    Java 读写锁是Java并发编程中的一种重要机制,它为多线程环境下的数据访问提供了更为精细的控制。在Java的`java.util.concurrent.locks`包中,`ReentrantReadWriteLock`类实现了读写锁的功能。这个锁允许多个读取者...

    多线程文件读写ThreadREADWrite

    在多线程环境下,直接对共享资源(如文件)进行读写操作可能导致数据冲突和不一致。例如,当一个线程正在写入数据时,另一个线程尝试读取,可能会读到不完整的或者错误的数据。为了解决这个问题,我们通常会使用线程...

    多线程、许可证、互斥量、信号量 API的使用

    通过多线程,程序可以在同一时间做更多的事情,如处理用户输入、读写数据和进行计算,从而提高程序的响应速度和效率。然而,多线程也带来了数据安全和竞态条件的问题,因此需要有效的同步机制来避免这些问题。 **...

    java多线程教程 java多线程教程

    Java多线程教程详解 Java多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个任务,提高程序...理解线程的生命周期、调度机制、同步互斥原理,以及如何避免和解决线程相关问题,是成为专业Java程序员的基础。

    操作系统进程同步和互斥的实验报告.doc

    操作系统进程同步和互斥是计算机科学中一个基础而重要的概念,涉及到多个进程或线程之间的同步和互斥问题。在本实验报告中,我们将通过编写程序实现进程同步和互斥,掌握有关进程(线程)同步与互斥的原理,以及解决...

    多线程(22)读写锁分离模式1

    总结来说,读写锁分离模式通过分离读锁和写锁,使得在多线程环境下,读操作可以并行执行,写操作保持互斥,从而优化了并发访问的效率。Java的`java.util.concurrent.locks.ReadWriteLock`接口提供了一种标准的实现...

    java线程程序实例

    总之,理解和掌握Java线程、死锁及锁机制对于编写高效、安全的多线程程序至关重要。通过实践和学习相关实例,我们可以更好地应对并发编程中的挑战,提升程序的并发性能和稳定性。在实际应用中,应根据具体需求选择...

    操作系统——实验四 windows中线程的创建和同步控制

    在windows的环境下,创建一个控制台进程,此进程创建两个并发线程,一个是读线程,另一个是写线程。这两个线程共享一个数组A,写...修改代码,使每次读写互斥,即每次对数组的写操作结束后才能进行写操作,反之亦然。

    java线程同步操作实例详解

    Java线程同步操作是指在多线程编程中,为了避免线程之间的数据不一致和混乱,采取的一种机制,以确保线程安全。Java提供了多种方式来实现线程同步,包括synchronized关键字、Lock接口、Atomic变量等。 一、...

Global site tag (gtag.js) - Google Analytics