以前一直不知道可重用锁,可重用体现在什么地方,现在理解了,可重用是指同一个线程如果已经保持了此锁,则后面再调用lock()方法后,还可以进入lock()后面的方法.
什么时候选择用 ReentrantLock 代替 synchronized
既然如此,我们什么时候才应该使用 ReentrantLock 呢?答案非常简单 —— 在确实需要一些 synchronized 所没有的特性的时候,比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者锁投票。 ReentrantLock 还具有可伸缩性的好处,应当在高度争用的情况下使用它,但是请记住,大多数 synchronized 块几乎从来没有出现过争用,所以可以把高度争用放在一边。我建议用 synchronized 开发,直到确实证明 synchronized 不合适,而不要仅仅是假设如果使用 ReentrantLock “性能会更好”。请记住,这些是供高级用户使用的高级工具。(而且,真正的高级用户喜欢选择能够找到的最简单工具,直到他们认为简单的工具不适用为止。)。一如既往,首先要把事情做好,然后再考虑是不是有必要做得更快。
public class Worker implements Runnable {
private final ReentrantLock lock = new ReentrantLock();
Worker() {
//Thread.currentThread().setName(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println("threadName [" + threadName + "] before lock");
lock.lock();
try {
System.out.println("threadName [" + threadName + "]in lock1");
lock.lock();
lock.unlock();
System.out.println("threadName [" + threadName + "]in lock2");
try {
Thread.currentThread().sleep(50000);
} catch (InterruptedException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
} finally {
lock.unlock();
System.out.println("threadName [" + threadName + "]unlock");
}
System.out.println("threadName [" + threadName + "] over");
}
public static void main(String[] args) {
Worker w = new Worker();
Thread t1 = new Thread(w);
t1.setName("thread-1");
Thread t2 = new Thread(w);
t2.setName("thread-2");
Thread t3 = new Thread(w);
t3.setName("thread-3");
t1.start();
t2.start();
t3.start();
}
}
分享到:
相关推荐
可重入锁,如`java.util.concurrent.locks.ReentrantLock`,允许一个线程多次进入同一锁定区域,这在递归方法中尤其有用。当线程试图重新进入已被其持有的锁时,它不会被阻塞。这与传统的非可重入锁形成对比,后者...
显式锁则是由java.util.concurrent.locks包中的Lock接口及其实现类提供,如ReentrantLock,它提供了更灵活的锁定策略,支持可中断和公平性锁。 并发集合是Java并发编程中的另一重要工具。例如,ConcurrentHashMap是...
8 锁的现象是 Java 中的一种并发编程模型,描述了 8 种不同的锁机制,它们是:公平锁、非公平锁、可重入锁、读写锁、StampedLock、LockSupport、AbstractQueuedSynchronizer(AQS)、ReentrantLock。这些锁机制可以...
ReentrantLock支持公平锁和非公平锁,还提供了尝试获取锁(tryLock)以及可中断锁等待等功能。 4. ** LockSupport 工具类**:此工具类提供了线程阻塞和唤醒的基础功能,可以配合Condition对象使用,实现更复杂的...
内置锁是`synchronized`的关键字实现,而显式锁则是`java.util.concurrent.locks`包中的`Lock`接口,如`ReentrantLock`,它提供了比`synchronized`更灵活的锁操作。 阻塞锁是指在获取锁失败时,线程会被阻塞直到...
`ReentrantLock`是`Lock`接口的一个实现,它是可重入的,即一个线程可以多次获取同一个锁,不会造成死锁。提供了公平锁和非公平锁两种模式,以及Condition对象来实现线程间的等待和唤醒。 #### 2.2. Condition(i) ...
`ReentrantLock`提供了比`synchronized`更灵活的锁定机制,包括尝试锁定、可中断锁定等。使用`ReentrantLock`时,需要显式地获取和释放锁。 ```java import java.util.concurrent.locks.ReentrantLock; public ...
显示锁是Java提供的显式加锁和解锁机制,如ReentrantLock,它是可重入的,意味着同一个线程可以多次获取同一个锁。独占锁是指一次只有一个线程可以持有锁,而共享锁允许多个线程共同持有。 死锁是多线程编程中的一...
13. **可重入锁(ReentrantLock)**:可重入锁允许一个线程多次获取同一锁,避免死锁。`ReentrantLock`提供与`synchronized`相似的功能,但具有更多控制选项,如公平锁、非公平锁、条件变量等。 14. **线程局部变量...
`ReentrantLock`提供了比`synchronized`更强大的锁定机制,比如公平锁、非公平锁、可中断等待等。 #### 3. 原子操作类 Java提供了原子操作类,用于支持无锁并发编程,可以避免使用锁带来的性能开销。常用的原子操作...
- **ReentrantLock**:这是可重入的互斥锁,比synchronized更灵活,支持公平锁和非公平锁,以及可中断和可定时的获取锁。 - **Condition**:Condition接口提供了比synchronized更细粒度的线程通信,可以创建多个...
- **显示锁**:通过`ReentrantLock`类实现,提供了比`synchronized`更灵活的锁操作,例如可重入性、非公平锁/公平锁的选择等。 - **读写锁**:通过`ReentrantReadWriteLock`类实现,允许多个读线程同时访问资源,但...
4. **线程同步**:Java中的`synchronized`关键字和`java.util.concurrent`包下的工具类(如Semaphore、ReentrantLock)可以帮助实现线程间的同步,确保在并发环境下的正确执行。 5. **线程池**:为了更有效地管理...
12. `Synchronized`与`ReentrantLock`的区别在于,前者是内置锁,后者是显式锁,`ReentrantLock`提供了更多的控制和更高的可扩展性。 13. 线程池的底层工作原理:通过维护一组可重用线程,避免频繁创建销毁线程的...
ReentrantLock支持公平和非公平锁,ReentrantReadWriteLock允许在读多写少的场景下提高并发性。Condition接口提供了条件变量的实现,允许线程在某个条件下等待。 5. 并发框架 Java提供了丰富的并发框架来简化并发...
### JDK_AQS解析 #### 概述 ...AQS的设计不仅提高了锁的可重用性,还极大地增强了灵活性和扩展性。通过学习AQS,我们不仅能更深入地了解Java并发库的内部实现,还能更好地利用这些工具解决实际问题。
此外,书中还讨论了Lock接口及其实现,如ReentrantLock,相比synchronized提供了更细粒度的锁控制和更丰富的特性,如尝试获取锁、可中断等待和公平锁等。这些高级锁机制能够帮助开发者写出更高效、更灵活的并发代码...
在线程编程中,同步和锁是保证线程安全不可或缺的机制。 #### 线程同步方法 Java提供了多种线程同步的方法,如synchronized关键字、显式锁(Lock)以及各种并发集合类。 #### 死锁与活锁 死锁是指两个或两个以上...
与synchronized不同,ReentrantLock支持公平锁和非公平锁策略,并且可以分离条件变量,这使得多路分支等待成为可能。 - Condition接口提供了等待/通知机制,允许更精确的线程同步。每个Lock实例可以有多个Condition...
例如,`ExecutorService`是一个线程池服务,它可以创建并管理一组可重用的工作线程,用于执行提交的任务。这比直接创建线程更加高效,因为线程池可以重用已创建的线程,减少线程创建和销毁的开销: ```java ...