1. synchronized是jvm层面的,lock是API层面的锁
使用如下代码验证
public class LockAndSynchronizedDemo {
public static void main ( String[ ] args) {
synchronized ( new Object ( ) ) {
}
new ReentrantLock ( ) ;
}
}
使用 javap -c LockAndSynchronizedDemo.class
得到字节码指令
public static void main ( java. lang. String[ ] ) ;
Code:
0 : new #2
3 : dup
4 : invokespecial #1
7 : dup
8 : astore_1
9 : monitorenter
10 : aload_1
11 : monitorexit
12 : goto 20
15 : astore_2
16 : aload_1
17 : monitorexit
18 : aload_2
19 : athrow
20 : new #3
23 : dup
24 : invokespecial #4
27 : pop
28 : return
注意点
synchronized
关键字解析出三条关键字节码指令,一条monitorenter
,两条monitorexit
(一个monitorexit是发生异常退出,一个monitorexit是正常退出 )new ReentrantLock()
只是执行了一条new对象的指令,证明了是代码层面的实现,和JVM底层没啥大关系
2. synchronized不需要解锁
synchronized不需要向lock一样执行lock.unlock()
操作
3. 等待是否可中断
synchronized不可以被中断,要等待就得一直等待 lock可以使用lock.interrupt()
方法进行中断,在等待期间去干别的事
4. synchronized是非公平锁
synchronized是非公平锁,不可更改 lock可以通过构造函数指定是公平锁还是非公平锁
5. 锁绑定多个条件Condition(精准唤醒)
1. synchronized要么notify(),要么notifyAll(),线程之间的唤醒方式太过单一
2. lock可以精准唤醒,conditionA可以唤醒conditionB,conditionB可以唤醒conditionC
精准唤醒的Condition代码举例
public class PrintDemo {
public static void main ( String[ ] args) {
PrintSource printSource = new PrintSource ( ) ;
new Thread ( ( ) - > {
printSource. print5 ( ) ;
} , "AAA" ) . start ( ) ;
new Thread ( ( ) - > {
printSource. print10 ( ) ;
} , "BBB" ) . start ( ) ;
new Thread ( ( ) - > {
printSource. print15 ( ) ;
} , "CCC" ) . start ( ) ;
}
}
class PrintSource {
private Lock lock = new ReentrantLock ( ) ;
private Integer number = 1 ;
Condition condition1 = lock. newCondition ( ) ;
Condition condition2 = lock. newCondition ( ) ;
Condition condition3 = lock. newCondition ( ) ;
public void print5 ( ) {
lock. lock ( ) ;
try {
while ( number != 1 ) {
condition1. await ( ) ;
}
for ( int i = 0 ; i < 5 ; i++ ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "\t " + i) ;
}
number = 2 ;
condition1. signal ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
public void print10 ( ) {
lock. lock ( ) ;
try {
while ( number != 2 ) {
condition2. await ( ) ;
}
for ( int i = 0 ; i < 10 ; i++ ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "\t " + i) ;
}
number = 3 ;
condition2. signal ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
public void print15 ( ) {
lock. lock ( ) ;
try {
while ( number != 3 ) {
condition3. await ( ) ;
}
for ( int i = 0 ; i < 15 ; i++ ) {
System. out. println ( Thread. currentThread ( ) . getName ( ) + "\t " + i) ;
}
number = 1 ;
condition3. signal ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
} finally {
lock. unlock ( ) ;
}
}
}