参考文章
synchronized 关键字的可重入性
在 java 中被 synchronized
关键字所修饰的代码块是支持重入的。 也就是说, 当一个java线程进入了某个对象的 synchronized
代码块后, 还能够再次进入该对象其他的synchronized
代码块。 需要重复进入同一个对象的 synchronized 方法的最常见情形是被 synchronized 修饰的递归方法 通过下面的例子可以很清晰的展示出synchronized
的可重入性。
public class Reentrance {
public synchronized void outter (){
System.out .println("enter outter " );
inner();
}
public synchronized void inner (){
System.out .println("enter inner" );
}
public static void main (String[] args) {
new Reentrance().outter();
}
}
output:
outter enter
inner enter
synchronized 关键字与ReentrantLock 区别
既然synchronized
关键字是支持重入的, 那么为什么还要引入 ReentrantLock
? ReentrantLock
与 synchronized
关键字的区别在哪
区别1: ReentrantLock
支持对锁的公平性(fairness)控制, synchronized
关键字不支持公平性的控制。
构造函数 ReentrantLock(boolean fair) 可以通过参数 boolean 值指定锁是需要将所提供给等待时间最长的线程还是随机竞争获得所。 区别2: ReentrantLock
提供了一个很synchronized 关键字不具备的方法 tryLock()
。 该方法仅仅当锁未被其他线程占用的时, 才会获取锁, 这样可以减少同一时刻阻塞在同一个锁上的线程数量。 区别3: ReentrantLock
在锁定期间, 是可以被其他线程打断的 (interrupt), synchronized
关键词的线锁修饰的方法是可以被长期或一直阻塞。 区别3: 正在等待 ReentrantLock
的线程是可以被中断的,而 synchronized
关键词则不具备这种能力。 区别4: ReentrantLock
还提供了获取所有等待锁线程的List 的方法 区别5: ReentrantLock
提供了条件变量Condition
的构造方法newCondition() 下面这个例子简单展示了如何使用ReentrantLock
进行代码的同步控制
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Java program to show, how to use ReentrantLock in Java.
* Reentrant lock is an alternative way of locking
* apart from implicit locking provided by synchronized keyword in Java.
*
* @author Javin Paul
*/
public class ReentrantLockHowto {
private final ReentrantLock lock = new ReentrantLock();
private int count = 0 ;
public int getCount () {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + " gets Count: " + count);
return count++;
} finally {
lock.unlock();
}
}
public synchronized int getCountTwo () {
return count++;
}
public static void main (String args[]) {
final ThreadTest counter = new ThreadTest();
Thread t1 = new Thread() {
@Override
public void run () {
while (counter.getCount() <= 6 ) {
try {
Thread.sleep(100 );
} catch (InterruptedException ex) {
ex.printStackTrace(); }
}
}
};
Thread t2 = new Thread() {
@Override
public void run () {
while (counter.getCount() <= 6 ) {
try {
Thread.sleep(100 );
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
};
t1.start();
t2.start();
}
}
Output:
Thread-0 gets Count: 0
Thread-1 gets Count: 1
Thread-1 gets Count: 2
Thread-0 gets Count: 3
Thread-1 gets Count: 4
Thread-0 gets Count: 5
Thread-0 gets Count: 6
Thread-1 gets Count: 7