對象的方法中一旦加入synchronized修飾,則任何時(shí)刻只能有一個(gè)線(xiàn)程訪(fǎng)問(wèn)synchronized修飾的方法。假設有個(gè)數據對象擁有寫(xiě)方法與讀方法,多線(xiàn)程環(huán)境中要想保證數據的安全,需對該對象的讀寫(xiě)方法都要加入 synchronized同步塊。
這樣任何線(xiàn)程在寫(xiě)入時(shí),其它線(xiàn)程無(wú)法讀取與改變數據;如果有線(xiàn)程在讀取時(shí),其他線(xiàn)程也無(wú)法讀取或寫(xiě)入。
這種方式在寫(xiě)入操作遠大于讀操作時(shí),問(wèn)題不大,而當讀取遠遠大于寫(xiě)入時(shí),會(huì )造成性能瓶頸,因為此種情況下讀取操作是可以同時(shí)進(jìn)行的,而加鎖操作限制了數據的并發(fā)讀取。
ReadWriteLock解決了這個(gè)問(wèn)題,當寫(xiě)操作時(shí),其他線(xiàn)程無(wú)法讀取或寫(xiě)入數據,而當讀操作時(shí),其它線(xiàn)程無(wú)法寫(xiě)入數據,但卻可以讀取數據 。
且看 以下例子
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
*
* @author soszou
* @date 2014-5-27
*
*/
public class ReadWriteLockDemo {
static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
Data data = new Data();
Worker t1 = new Worker(data, false);
Worker t2 = new Worker(data, true);
t1.start();
t2.start();
}static class Worker extends Thread {
Data data;
boolean read;public Worker(Data data, boolean read) {
this.data = data;
this.read = read;
}public void run() {
if (read)
data.get();
else
data.set();
}
}static class Data {
ReadWriteLock lock = new ReentrantReadWriteLock();
Lock read = lock.readLock();
Lock write = lock.writeLock();public void set() {
write.lock();
System.out.println(Thread.currentThread().hashCode() + " set:begin "
+ sdf.format(new Date()));
try {
Thread.sleep(5000);
//
} catch (Exception e) {} finally {
System.out.println(Thread.currentThread().hashCode() + " set:end "
+ sdf.format(new Date()));
write.unlock();
}}
public int get() {
read.lock();
System.out.println(Thread.currentThread().hashCode() + " get :begin "
+ sdf.format(new Date()));
try {
Thread.sleep(5000);
//
} catch (Exception e) {} finally {
System.out.println(Thread.currentThread().hashCode() + " get :end "
+ sdf.format(new Date()));
read.unlock();
}
return 1;
}
}
}
兩個(gè)線(xiàn)程均是讀線(xiàn)程,結果如下
8637543 get :begin 2014-05-27 15:40:10
30771886 get :begin 2014-05-27 15:40:10
30771886 get :end 2014-05-27 15:40:15
8637543 get :end 2014-05-27 15:40:15
兩讀線(xiàn)程均可同時(shí)讀取數據,下面看一個(gè)是讀線(xiàn)程,一個(gè)寫(xiě)線(xiàn)程的情況
Data data = new Data();
Worker t1 = new Worker(data,false);
Worker t2 = new Worker(data,true);
t2.start();
Thread.sleep(100);
t1.start();
先啟動(dòng)讀取線(xiàn)程,再啟動(dòng)寫(xiě)入線(xiàn)程,看結果
771886 set:begin 2014-05-27 15:42:11
30771886 set:end 2014-05-27 15:42:16
14577460 get :begin 2014-05-27 15:42:16
14577460 get :end 2014-05-27 15:42:21
可以看到讀取線(xiàn)程工作時(shí),寫(xiě)入線(xiàn)程是不能訪(fǎng)問(wèn)數據的
聯(lián)系客服