Lock
lock比synchronized更加面向对象,在传统synchronized中锁和监视器是同一个对象。在Lock中将其分离了出来,容我一一道来。Lock是java.util.concurrent.locks中的一个顶层接口。
package com.hb;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
public static void main(String[] args) {
new LockTest().init();
}
public void init() {
final Outputer output = new Outputer();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
output.output("hbbb");
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
output.output("china");
}
}
}).start();
}
class Outputer {
// jdk1.5的锁技术
private 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();
} finally {
// 不管怎么样,拿了锁最后一定要释放,自己不放,没有人能放。
lock.unlock();
}
}
}
}
读写锁:
读写锁分为读锁和写锁,写锁和写锁互斥,写锁与读锁互斥,读锁与读锁不互斥。这是jvm自己控制的,上好对应的锁就可以了,为什么读锁与读锁不互斥呢?上锁是为了防止线程出现安全问题,多个人读而已,又不会修改数据。所以是可以的。
下面来看看一个面试题:
package com.hb;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class CacheDemo {
/**
* 面试题:写一个缓存系统
*/
// 缓存器
private Map<String, Object> cache = new HashMap<String, Object>();
private ReadWriteLock rwl = new ReentrantReadWriteLock();
public Object get(String key) {
rwl.readLock().lock();
Object value = null;
try {
value = cache.get(key);
// 如果value为null,开闭读锁,开启写锁。
if (value == null) {
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
if (value == null) {// 怕有多余的写锁进来
value = "abc";// 实际去queryDB
}
} finally {
rwl.writeLock().unlock();
}
rwl.readLock().lock();
}
} finally {
rwl.readLock().unlock();
}
return value;
}
}
Condition
Condition可以实现线程间的通信,在等待Conditon时,可能会发生伪唤醒,应该将其定义在一个循环中等待唤醒。一个锁的内部可以有多个Condition,即有多路等待和通知,可以参考api给出的Condition演示。
package com.hb;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ConditionCommunication {
/**
*
* 面试题:
* 子线程循环10次,主线程循环20次,接着又是子线程循环10次,主线程循环20次,如此重复50次。
*/
public static void main(String[] args) {
final Business b=new Business();
new Thread(new Runnable(){
@Override
public void run() {
for(int i =1;i<=50;i++){
b.sub1(i);
}
}
}).start();
for(int i=1;i<=50;i++){
b.main(i);
}
}
//将需要同步的代码提取出来单独存在,这样可以提高代码的扩展性等。
static class Business{
private Lock lock=new ReentrantLock();
private Condition condition1=lock.newCondition();
private Condition condition2=lock.newCondition();
private boolean flag =true;
public void sub1(int i){
//如果不是我,那就等待,由于线程存在伪唤醒的情况,所以给整个while()
lock.lock();
try{
while(!flag){
try {
condition1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j =1;j<=10;j++){
System.out.println("sub thread sequence of "+j+" ,loop of "+i);
}
flag=false;
condition2.signal();
}finally{
lock.unlock();
}
}
public void main(int i ){
lock.lock();
try{
while(flag){
try {
condition2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for(int j =1;j<=20;j++){
System.out.println("main thread sequence of "+j+" ,loop of "+i);
}
flag=true;
condition1.signal();
}finally{
lock.unlock();
}
}
}
}