最近看了看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.完成操作一定要解锁!
测试例子:(比较多,总之在读完所有的字符以前不出现混乱读取)
相关推荐
操作系统中的线程同步与互斥是并发编程中的关键概念,它们确保了多线程环境下的程序正确性和资源安全。线程互斥是指当多个线程访问同一临界资源时,同一时刻只允许一个线程进行操作,以防止数据竞争和不一致的状态。...
在这个“多线程编程和操作系统线程同步互斥演示”中,作者可能创建了一个或多个人工场景,展示了如何在VC++环境中使用多线程,并且演示了线程同步和互斥的实践应用。这可能涉及到以下几个方面: 1. **线程创建**:...
互斥锁确保在任何时候只有一个线程能访问共享资源,而监视器(如Java中的`synchronized`关键字)则提供了更高层次的抽象,它不仅提供互斥,还允许线程等待其他线程释放资源。 在读取文件时,多线程可能带来性能提升...
6. **读写锁(ReadWriteLock)**:Java 中的 ReentrantReadWriteLock 允许多个线程同时读取共享资源,但在写操作时仍然保持互斥,这样可以提高系统的并发性能。 7. **死锁(Deadlock)**:当两个或更多的线程相互...
- **文件操作**:在多个线程或进程中,如果需要对同一个文件进行读写操作,使用互斥锁可以防止数据的混乱,确保每次只有一个线程或进程进行读写。 - **全局变量**:当多个线程需要修改全局变量时,互斥锁能确保...
}`来避免读线程间的互斥,以及如何通过`wait`和`notifyAll`方法协调读写线程之间的同步。 ### 总结 读写锁是并发编程中一种重要的锁机制,尤其适用于读多写少的场景。在Java中,`ReentrantReadWriteLock`提供了...
在Java中,实现读写线程的同步通常有两种策略:互斥访问和读者-写者问题。"读者优先"的策略是一种解决读者-写者问题的方式,它允许同时有多个读者访问资源,但当有写者时,所有读写操作都必须暂停,直到写者完成其...
1. synchronized关键字:用于保证线程安全,它可以修饰方法或代码块,实现对共享资源的互斥访问。 2. volatile关键字:保证变量的可见性和有序性,但不保证原子性。 3. Lock接口与ReentrantLock类:提供了比...
线程是操作系统分配处理器时间的基本单位,每个线程都有自己的程序计数器、栈和局部变量,但共享同一块内存空间。这意味着多个线程可以访问相同的资源,这在读写操作中可能引发问题,因为如果一个线程正在写入数据,...
### 第20章 Part3:多线程互斥与协作 ...综上所述,互斥和协作是线程编程中的两个核心概念,对于编写高效稳定的多线程应用程序至关重要。通过正确理解和应用这些概念,开发者可以有效地避免竞态条件和其他并发问题。
Java 读写锁是Java并发编程中的一种重要机制,它为多线程环境下的数据访问提供了更为精细的控制。在Java的`java.util.concurrent.locks`包中,`ReentrantReadWriteLock`类实现了读写锁的功能。这个锁允许多个读取者...
在多线程环境下,直接对共享资源(如文件)进行读写操作可能导致数据冲突和不一致。例如,当一个线程正在写入数据时,另一个线程尝试读取,可能会读到不完整的或者错误的数据。为了解决这个问题,我们通常会使用线程...
通过多线程,程序可以在同一时间做更多的事情,如处理用户输入、读写数据和进行计算,从而提高程序的响应速度和效率。然而,多线程也带来了数据安全和竞态条件的问题,因此需要有效的同步机制来避免这些问题。 **...
Java多线程教程详解 Java多线程是Java编程中不可或缺的一部分,它允许程序同时执行多个任务,提高程序...理解线程的生命周期、调度机制、同步互斥原理,以及如何避免和解决线程相关问题,是成为专业Java程序员的基础。
操作系统进程同步和互斥是计算机科学中一个基础而重要的概念,涉及到多个进程或线程之间的同步和互斥问题。在本实验报告中,我们将通过编写程序实现进程同步和互斥,掌握有关进程(线程)同步与互斥的原理,以及解决...
总结来说,读写锁分离模式通过分离读锁和写锁,使得在多线程环境下,读操作可以并行执行,写操作保持互斥,从而优化了并发访问的效率。Java的`java.util.concurrent.locks.ReadWriteLock`接口提供了一种标准的实现...
总之,理解和掌握Java线程、死锁及锁机制对于编写高效、安全的多线程程序至关重要。通过实践和学习相关实例,我们可以更好地应对并发编程中的挑战,提升程序的并发性能和稳定性。在实际应用中,应根据具体需求选择...
在windows的环境下,创建一个控制台进程,此进程创建两个并发线程,一个是读线程,另一个是写线程。这两个线程共享一个数组A,写...修改代码,使每次读写互斥,即每次对数组的写操作结束后才能进行写操作,反之亦然。
Java线程同步操作是指在多线程编程中,为了避免线程之间的数据不一致和混乱,采取的一种机制,以确保线程安全。Java提供了多种方式来实现线程同步,包括synchronized关键字、Lock接口、Atomic变量等。 一、...