前言
多个线程对单一变量进行进行读取和赋值的操作会引发同步的问题
如下图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 {
//
// }
// }
}
}
读写锁在多线程 高并发 缓存系统中常常会使用到