一、API层面
· synchronized既可以修饰方法,也可以修饰代码块
//synchronized修饰一个方法时,这个方法叫同步方法
public synchronized void test1(){
doSomethingNeedSynchronizing();
}
public void test2(){
doSomethingNotNeedSynchronizing();
//synchroized修饰代码块时,包含两部分:锁对象的引用和这个锁保护的代码块
//括号中表示需要锁的对象lock,线程执行的时候会对lock上锁,执行完后释放
synchronized(obj){
doSomethingNeedSynchronizing();
}
}
· ReentrantLock的使用主要是获得锁和释放锁
public void test3(){
try{
lock.lock();
doSomethingNeedSynchronizing();
}finally{
lock.unlock();
}
}
二、ReentrantLock可实现公平锁
· synchronized的锁是非公平锁,ReentrantLock默认生成的也是非公平锁,但是可通过参数fair设置为公平锁。
· 公平锁 :加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得
非公平锁 :加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待
三、ReentrantLock等待可中断
· 使用synchronized,假如线程A获得了锁且一直不释放,那么线程B会一直等待下去,不能被中断
· 同样情形下,使用ReentrantLock可以通过tryLock()、tryLock(timeout,unit)、lockInterruptibly()使B线程不用一直等待
四、锁绑定多个条件
· ReentrantLock可以同时绑定多个Condition对象,只需多次调用newCondition()方法即可。
· synchronized中,锁对象的wait()和notify()或notifyAll()方法可以实现一个隐含的条件。但如果要和多于一个的条件关联的时候,就不得不额外添加一个锁。
五、ReentrantLock的两种使用方法
· 同使用synchronized一样,A线程拿到锁一直不释放,B线程会一直等待
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
MyRunnable myRunnable = new MyRunnable(lock);
new Thread(myRunnable).start();
new Thread(myRunnable).start();
}
}
class MyRunnable implements Runnable {
private ReentrantLock lock;
public MyRunnable(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
lock.lock();
System.out.println(Thread.currentThread() + " get lock");
while(true){
System.out.println(Thread.currentThread() + " hold lock");
}
} finally {
System.out.println(Thread.currentThread() + " release lock");
lock.unlock();
}
}
}
· 每个线程都会去尝试拿锁,如果拿到了则处理需要同步处理的方法(处理完后需要释放锁),否则则去处理其他不需要同步处理的任务
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
MyRunnable myRunnable = new MyRunnable(lock);
new Thread(myRunnable).start();
new Thread(myRunnable).start();
}
}
class MyRunnable implements Runnable {
private ReentrantLock lock;
public MyRunnable(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
try {
// 尝试在3秒时间内获取锁
// 如果获取到锁,则返回true
// 否则会阻塞3秒,直到获取锁或者3秒过后
if (lock.tryLock(3, TimeUnit.SECONDS)) {
try {
System.out.println(Thread.currentThread() + " get lock");
System.out.println(Thread.currentThread() + " hold lock 1 second");
TimeUnit.SECONDS.sleep(1);
} finally {
System.out.println(Thread.currentThread() + " release lock");
lock.unlock();
}
}else{
System.out.println(Thread.currentThread() + " do not get lock within 3 seconds");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}