Lock
Lock是Java提供給開發(fā)者JDK級別的一種控制代碼同步訪問的工具類揖闸。只有一個子類ReentrantLock。功能和synchronized差不多料身。使用也是非常的簡單
class Test {
private Lock lock = new ReentrantLock();
//需要同步訪問的方法
private void doSomething() {
lock.lock();
try {
//do something
} catch (Exception e) {
}finally {
lock.unlock();
}
}
}
例子
private void lockTest() {
sendMessage("lockTest begin");
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
doSomething();
}
sendMessage("thread-1 end");
}
}, "thread-1").start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
doSomething();
}
sendMessage("thread-2 end");
}
}, "thread-2").start();
}
//一次訪問這個函數(shù)
private void doSomething() {
lock.lock();
try {
Thread.sleep(100);
sendMessage(Thread.currentThread().getName() + " doSomething");
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
輸出:
ReadWriteLock
同步讀寫操作的一個鎖汤纸。和Lock完全沒有任何關(guān)系。
- 允許多個線程同時進(jìn)行讀操作芹血。
- 不允許多個線程同時寫操作贮泞,只會誰拿到鎖誰先去執(zhí)行寫操作。
- 多個線程既有讀又有寫操作幔烛,沒有線程進(jìn)入寫或者等待寫啃擦,就可以多個線程讀了;進(jìn)入寫操作后饿悬,不允許其他線程讀或者寫
讀操作
private void readLockTest() {
new Thread(new Runnable() {
@Override
public void run() {
readSomething();
}
}, "t1").start();
new Thread(new Runnable() {
@Override
public void run() {
readSomething();
}
}, "t2").start();
}
private void readSomething() {
readWriteLock.readLock().lock();
try {
Iterator<String> iterator = cacheList.iterator();
while (iterator.hasNext()) {
Thread.sleep(100);
sendMessage(Thread.currentThread().getName() + "讀取 -- "+ iterator.next());
}
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
readWriteLock.readLock().unlock();
}
}
輸出:
寫操作
private void writeLockTest() {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
writeSomething();
}
}, "t1");
t1.start();
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
writeSomething();
}
}, "t2");
t2.start();
new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
sendMessage("寫完了");
for (String s : cacheList) {
sendMessage(s);
}
}
}).start();
}
private void writeSomething() {
readWriteLock.writeLock().lock();
try{
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
cacheList.add("這是第" + i + "元素");
sendMessage(Thread.currentThread().getName() + "寫入---這是第" + i + "元素");
}
}catch (InterruptedException e) {
e.printStackTrace();
}finally {
readWriteLock.writeLock().unlock();
}
}
輸出:
讀寫同時進(jìn)行
private void readWriteLockTest(){
new Thread(new Runnable() {
@Override
public void run() {
writeSomething();
}
}, "t1").start();
new Thread(new Runnable() {
@Override
public void run() {
readSomething();
}
}, "t2").start();
new Thread(new Runnable() {
@Override
public void run() {
readSomething();
}
}, "t3").start();
new Thread(new Runnable() {
@Override
public void run() {
writeSomething();
}
}, "t4").start();
輸出:
測試方法中有四個線程令蛉,分別是:寫,讀狡恬,讀言询,寫;日志中在t2讀的時候傲宜,這是t3啟動了运杭,t3是讀的操作,此時并沒有寫或者等待寫的操作函卒,所以t3也開始讀辆憔,最終t2和t3同時讀。
把測試方法順序改一下报嵌,分別是:寫虱咧,讀,寫讀锚国;
輸出:
可以看出在t2的時候腕巡,t3啟動了,因?yàn)閠3是寫操作血筑,所以t4啟動后绘沉,因?yàn)閠3已經(jīng)等待寫,所以t4會在t3寫完后才執(zhí)行豺总。