1.Lock
比传统线程模型中的synchronized方式更加面向对象,和生活中的锁类似,锁本身也应该是一个对象,两个线程执行的代码片段要实现同步互斥的效果,他们必须用同一个Lock对象
eg:改进传统的线程同步
package com.qunar.thread;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadLock {
public static void main(String[] args) {
new ThreadLock().init();
}
private void init() {
final Outputer outputer = new Outputer();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("suhao");
}
}
}).start();
new Thread(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("liushourun");
}
}
}).start();
}
static class Outputer {
Lock lock = new ReentrantLock();
public void output(String name) {
int len = name.length();
lock.lock();
try {
for (int i = 0; i < len; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} catch (Exception e) {
}finally{
lock.unlock();
}
}
}
}
2.读写锁:
读写互斥 写写互斥 读读不互斥
由JVM自己控制,只要加上对应的锁就行了。
eg:
package com.qunar.thread;
import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadAndWriteLock {
public static void main(String[] args) {
final Queue3 q3 = new Queue3();
for(int i = 0;i<3;i++){
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
q3.get();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
q3.put(new Random().nextInt(10000));
}
}
}).start();
}
}
}
class Queue3{
private Object dataObject;
ReadWriteLock rwlLock = new ReentrantReadWriteLock();
public void get(){
rwlLock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName()+"be ready to read data");
Thread.sleep((long)(Math.random()*1000));
System.out.println(Thread.currentThread().getName()
+ "have read data"+dataObject);
} catch (Exception e) {
e.printStackTrace();
}finally{
rwlLock.readLock().unlock();
}
}
public void put(Object data){
rwlLock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName()
+ "be ready to write data");
Thread.sleep((long)(Math.random()*1000));
this.dataObject = data;
System.out.println(Thread.currentThread().getName()
+ "have write data"+data);
} catch (Exception e) {
e.printStackTrace();
}finally{
rwlLock.writeLock().unlock();
}
}
}
3.实现一个缓存 系统
示例用法。下面的代码展示了如何利用重入来执行升级缓存后的锁降级(为简单起见,省略了异常处理):
class CachedData {
Object data;
volatile boolean cacheValid;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
rwl.readLock().unlock();
rwl.writeLock().lock();
// Recheck state because another thread might have acquired
// write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.readLock().lock();
rwl.writeLock().unlock(); // Unlock write, still hold read
}
use(data);
rwl.readLock().unlock();
}
}
实际实现
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 缓存系统,使用读写锁实现
* @author hao.su
*
*/
public class CacheDemo {
private Map<String, Object> cache = new HashMap<String, Object>();
private ReadWriteLock rwl = new ReentrantReadWriteLock();
/**
* 多个线程之间可以并发的读,
* @param key
* @return
*/
public Object getData(String key) {
rwl.readLock().lock();
Object data = null;
try {
data = cache.get(key);
if (data == null) {
rwl.readLock().unlock();
rwl.writeLock().lock();
if(data == null){
try{
data = "aaaa";// 到数据库中查找
}finally{
rwl.writeLock().unlock();
}
}
rwl.readLock().lock();
}
} catch (Exception e) {
e.printStackTrace();
}finally{
rwl.readLock().unlock();
}
return data;
}
}