前言
多个线程对单一变量进行进行读取和赋值的操作会引发同步的问题
如下图5个线程中4个线程对1个变量i进行读操作
1个线程对i进行自加1操作。红圈处就出现了数据不正常情况。
于是我们加入了synchronized关键字耗时4000毫秒 如下
public static class ReadWriteService{ //以下使用非读写锁的传统示例synchronized 耗时4000 int testNum = 0;
public synchronized int get() {
int i = -1;
try {
Thread.sleep(10);//耗时
i = testNum;
} catch (Exception e) {
} finally {
}
return i;
}
public synchronized void put(int num) {
try {
Thread.sleep(20);//耗时
testNum = num;
System.out.println("写入" + this.get());
} catch (Exception e) {
} finally {
}
} }
正题
过去我们对一个文件读写需要同步,后来发觉
我们有N个线程读取数据的时候,可以不需要同步
只有存数据的时候需要同步。
这在JAVA1.5以前是无法做到的。JAVA加入了Lock对象 其子类ReadWriteLock可以轻松帮我们实现该方案。
(Lock的使用方法与synchronized基本相同,但是更加面向对象。和更多新功能)
public void run() { // TODO Auto-generated method stub synchronized (this) { //doing something } }
等价于以下代码。
Lock lock=new ReentrantLock(); @Override public void run() { // TODO Auto-generated method stub lock.lock(); //doing something lock.unlock(); }
开启5个线程,4个线程进行读操作,1个线程进行写操作
以下是代码示例
package demo.lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class ReadWriteLockDemo { static int testNum = 0; static long beginTime = System.currentTimeMillis(); public static void main(String[] args) { // TODO Auto-generated method stub final ReadWriteService rw = new ReadWriteService(); //开启5个线程 for (int i = 0; i < 5; i++) { final int id = i; new Thread() { public void run() { //直到计数达到100 while (testNum <= 100) { //线程中的4个读取数据 else中的一个1个写入数据 if (id < 4) { System.out.println("读取" + rw.get() + "消耗时间 " + (System.currentTimeMillis() - beginTime)); } else { rw.put(testNum++); } } } }.start(); } } //将同步的代码写在同一个类中体现,面向对象,内聚性,封装性。 public static class ReadWriteService{ //读写锁 读与读之间不互斥,读与写互斥。 ReadWriteLock rwLock = new ReentrantReadWriteLock(); //测试用的同步数据变量 int testNum = 0; //以下使用读写锁的示例 耗时3000 public int get() { int i = -1; rwLock.readLock().lock(); try { Thread.sleep(10);//耗时 i = testNum; } catch (Exception e) { // TODO: handle exception } finally { rwLock.readLock().unlock(); } return i; } public void put(int num) { rwLock.writeLock().lock(); try { Thread.sleep(20);//耗时 testNum = num; System.out.println("写入" + this.get()); } catch (Exception e) { // TODO: handle exception } finally { rwLock.writeLock().unlock(); } } //以下使用非读写锁的传统示例synchronized 耗时4000 // public synchronized int get() { // int i = -1; // try { // Thread.sleep(10);//耗时 // i = testNum; // } catch (Exception e) { // } finally { // } // return i; // // } // public synchronized void put(int num) { // try { // Thread.sleep(20);//耗时 // testNum = num; // System.out.println("写入" + this.get()); // } catch (Exception e) { // } finally { // // } // } } }
读写锁在多线程 高并发 缓存系统中常常会使用到