一、原始构成
synchronized是关键字属于JVM层面,monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖monitor对象只有在同步代码块和同步方法中才能调用wait/notify等方法)
Lock是具体的类,是api层面的锁;
二、使用方法
synchronized不需要用户手动释放锁,synchronized代码执行完成以后系统会自动让线程释放对锁的占有
ReentrantLock则需要用户手动去释放锁,若没有主动释放锁,就有可能导致死锁现象。需要使用lock()和unlock()方法配合try finally语句块来完成。
三、等待是否可以中断
synchronized不可中断,除非抛出异常或者正常运行完成。
ReetrantLock可中断,
1. 设置超时方法tryLock(long timeout, TimeUnit unit);
2.lockInterruptibly()放入代码块中,调用interrupt()方法可中断;
四、加锁是否公平
synchronized是非公平锁
ReentrantLock默认是非公平锁,可设置为公平锁。
五、锁绑定多个条件condition
synchronized没有;
ReentrantLock用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized要么随机唤醒一个,要么唤醒全部线程。
六、案例
题目:多线程之间按找顺序调用,实现A->B->C三个线程启动,要求如下:
AA打印5次,BB打印10次,CC打印15次,重复上述过程10次.
class ShareResource{
private int number = 1; // A:1, B:2, C:3
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
public void print5(){
try {
lock.lock();
while (number != 1){
conditionA.await();
} for (int i = 1; i <= 5; i++){
System.out.print("A");
}
System.out.println();
number++;
conditionB.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void print10(){
try {
lock.lock();
while (number != 2){
conditionB.await();
} for (int i = 1; i <= 10; i++){
System.out.print("B");
}
System.out.println();
number++;
conditionC.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public void print15(){
try {
lock.lock();
while (number != 3){
conditionC.await();
} for (int i = 1; i <= 15; i++){
System.out.print("C");
}
System.out.println();
number = 1;
conditionA.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public class SynchronizedLockDifference { public static void main(String[] args) {
ShareResource shareResource = new ShareResource();
new Thread(()->{
for (int i = 1; i <= 10; i++){
shareResource.print5();
}
}, "A").start(); new Thread(()->{
for (int i = 1; i <= 10; i++){
shareResource.print10();
}
}, "B").start(); new Thread(()->{
for (int i = 1; i <= 10; i++){
shareResource.print15();
}
}, "C").start(); }
}
输出结果:
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC
AAAAA
BBBBBBBBBB
CCCCCCCCCCCCCCC Process finished with exit code 0