关于Lock与synchronized关键字在锁的处理上的重要差别
- 1.锁的获取方式:前者是通过程序代码的方式由开发者手工获取,后者是通过JVM来获取(无需开发者干预)
- 2.具体实现方式:前者是通过Java代码的方式来实现,后者是通过JVM底层来实现_ (无需开发者关注)
- 3.锁的释放方式:前者务必通过unlock()方法在finally块中手工释放,后者是通过JVM来释放(无需开发者关注)
- 4.锁的具体类型:前者提供了多种,如公平锁、非公平锁,后者与前者均提供了可重入锁
-
传统上,我们可以通过synchronized关键字 + wait + notify/notifyAll 来实现多个线程之间的协调与通信,整个过程都是由JVM来帮助我们实现的;开发者无需(也是无法)了 解底层的实现细节
-
从JDK 5开始,并发包提供了Lock, Condition(await与signal/signalA11 )来实现多个线程之间的协调与通信,整个过程都是由开发者来 控制的,而且相比于传统方式,更加灵活,功能也更加强大
3.Thread. sleep与await. (或是Object的wait方法) 的本质区别: sleep方法本质.上不会释放锁,而await会释放锁, 并且在signal后,还需要重新获得锁才能继续执行(该行为与object的wait方法完全一致)
public class MyTest2 {
public static void main(String[] args) {
BoundedContainer bc = new BoundedContainer();
IntStream.range(0, 10).forEach(i -> new Thread(() -> {
try {
bc.take();
} catch (Exception e) {
}
}).start());
IntStream.range(0, 10).forEach(i -> new Thread(() -> {
try {
bc.put("hello");
} catch (Exception e) {
}
}).start());
}
}
class BoundedContainer {
private String[] elements = new String[10];
private Lock lock = new ReentrantLock();
private Condition notEmptyCondition = lock.newCondition();
private Condition notFullCondition = lock.newCondition();
private int elementCount; //已有的元素数量
private int putIndex;
private int takeIndex;
public void put(String ele) throws InterruptedException {
this.lock.lock();
try {
//如果所有位置已放满
while (elementCount == elements.length) {
notFullCondition.await();
}
this.elements[putIndex] = ele;
if (++putIndex == elements.length) {
putIndex = 0;
}
elementCount++;
System.out.println("put: " + Arrays.toString(elements));
notEmptyCondition.signal();
} finally {
this.lock.unlock();
}
}
public void take() throws InterruptedException {
this.lock.lock();
try {
while (elementCount == 0) {
notEmptyCondition.await();
}
this.elements[takeIndex] = null;
elementCount--;
if (++takeIndex == elements.length) {
takeIndex = 0;
}
System.out.println("take: " + Arrays.toString(elements));
notFullCondition.signal();
} finally {
this.lock.unlock();
}
}
}
网友评论