一. Lock
Lock 锁与 synchronized 的区别
- 两种锁都是重入锁
- synchronized在代码执行完毕,或抛出异常时会自动释放锁,Lock锁在代码执行完毕或抛出异常不会自动释放锁,需要手动调用unlock()方法手动释放锁
- Lock 可以调用tryLocak() 方法去尝试获取锁,如果返回true则说明获取到了锁,如果返回false则说明当前不能获取锁
Lock 常用方法与使用示例
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest {
//创建Lock对象锁,(ReentrantLock是Lock接口的实现)
private Lock lock = new ReentrantLock();
public static void main(String[] args) {
//使用final修饰,是因为匿名内部类中不允许有变量
final LockTest lockTest = new LockTest();
//线程1
/*匿名内部类方式创建子线程,并给子线程命名*/
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
lockTest.method(Thread.currentThread());
}
}, "t2");
t1.start();
t2.start();
}
//需要参与同步的方法
private void method(Thread thread) {
/*示例1,lock()方法获取锁
//获取锁,如果获取不到,则一直等待
lock.lock();
try {
System.out.println("线程名"+thread.getName() + "获得了锁");
}catch(Exception e){
e.printStackTrace();
} finally {
System.out.println("线程名"+thread.getName() + "释放了锁");
//由于Lock方式获取到的锁需要手动释放,需要使用try--catch在finally
//中手动释放锁,防止代码报错时,代码无法正常执行,锁无法释放
lock.unlock();
}*/
//tryLock(),获取锁,如果获取到锁,返回boolean值true否则为false
//可以根据是否获取到锁进行指定操作
//相同还设有tryLock(long timeout,TimeUnit unit)方法,如果获取到了锁返回true
//如果没有获取到锁会等待指定时间unit,如果这个时间内还是获取不到锁返回false
/*示例2,tryLock()方法获取锁, 此方法的执行最终都在finally中释放了锁*/
if (lock.tryLock()) {
try {
System.out.println("线程名" + thread.getName() + "获得了锁");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("线程名" + thread.getName() + "释放了锁");
lock.unlock();//释放锁
}
} else {
System.out.println("我是" + Thread.currentThread().getName() + "有人占着锁");
}
}
}
二. ReentrantReadWriteLock
ReentrantReadWriteLock 可以看为读读共享,读写,写读排它,当线程执行被ReentrantReadWriteLock 修饰的代码时,首先获取的是读锁,当有读操作改为写操作时会升级为写锁,当其他线程如果要做写的操作时当前线程也会升级为写锁,读锁时允许其他线程执行做读的操作,写锁时则不允许
/*如果有一个线程已经占用了读锁,则此时其他线程
如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
如果有一个线程已经占用了写锁,则此时其他线程如果申请
写锁或者读锁,则申请的线程会一直等待释放写锁*/
public class Test {
//创建读取锁对象(当同步时,如果如果读取操作线程也会等待,影响效率,解决
//这个问题使用读取锁)
private u rwl = new ReentrantReadWriteLock();
public static void main(String[] args) {
final Test test = new Test();
//匿名内部类方式创建线程类并运行
//线程类的run方法找那个调用test类的get方法
new Thread(){
public void run() {
test.get(Thread.currentThread());
};
}.start();
new Thread(){
public void run() {
test.get(Thread.currentThread());
};
}.start();
}
public void get(Thread thread) {
//获取读取锁
rwl.readLock().lock();
try {
long start = System.currentTimeMillis();
while(System.currentTimeMillis() - start <= 1) {
System.out.println(thread.getName()+"正在进行读操作");
}
System.out.println(thread.getName()+"读操作完毕");
} finally {
//释放读取锁
rwl.readLock().unlock();
}
}
}