Lock对象的使用
1. ReentrantLock
- 使用ReentrantLock可以实现同步;
- 使用ReentrantLock结合Condition类可以实现“选择性通知”,这个功能是Condition类默认提供的。Condition对象的作用是控制并处理线程的状态,它可以使线程呈wait状态,也可以让线程继续运行;
- 默认情况下,ReentrantLock类使用的是非公平锁。
Condition对象的await()方法:作用是使当前线程在接到通知或被中断之前一直处于等待wait状态,它和wait()方法的作用是一样的。其次,必须在condition.await()方法调用之前使用lock.lock()代码获得锁。
- Object类中的wait()方法相当于Condition类中的await()方法。
- Object类中的wait(long timeout)方法相当于Condition类中的await(long time,TimeUnit unit)方法。
- Object类中的notify()方法相当于Condition类中的signal()方法。
- Object类中的notifyAll()方法相当于Condition类中的signalAll()方法。
2. 公平锁与非公平锁
公平锁:采用先到先得的策略,每次获取锁之前都会检查队列里面有没有排队等待的线程,没有才会尝试获取锁,如果有就将当前线程追加到队列中。
非公平锁:采用“有机会插队”的策略,一个线程获取锁之前要先去尝试获取锁而不是在队列中等待,如果获取锁成功,则说明线程虽然是后启动的,但先获得了锁,这就是“作弊插 队” 的效果。如果获取锁没有成功,那么才将自身追加到队列中进行等待。
public class Service { public Lock lock; public Service(boolean fair){ lock = new ReentrantLock(fair); } public void testMethod(){ try { lock.lock(); System.out.println("testMethod" + Thread.currentThread().getName()); Thread.sleep(500); lock.unlock(); } catch (InterruptedException e) { e.printStackTrace(); } } } public class MyThread extends Thread{ private Service service; public MyThread(Service service){ super(); this.service = service; } @Override public void run() { service.testMethod(); } } public class Test { public static void main(String[] args) throws InterruptedException { Service service = new Service(false); MyThread[] thread1 = new MyThread[5]; MyThread[] thread2 = new MyThread[5]; for (int i = 0; i < 5; i++) { thread1[i] = new MyThread(service); thread1[i].setName("thread1+++" + (i + 1)); } for (int i = 0; i < 5; i++) { thread2[i] = new MyThread(service); thread2[i].setName("thread2---" + (i + 1)); } for (int i = 0; i < 5; i++) { thread1[i].start(); } Thread.sleep(500); for (int i = 0; i < 5; i++) { thread2[i].start(); } } } //输出结果如下 testMethodthread1+++1 testMethodthread2---1 testMethodthread1+++2 testMethodthread1+++3 testMethodthread1+++4 testMethodthread1+++5 testMethodthread2---5 testMethodthread2---3 testMethodthread2---4 testMethodthread2---2 //显然后启动的进程先抢到了锁,说明这是非公平锁 //修改为公平锁 Service service = new Service(true); //运行结果如下: testMethodthread1+++1 testMethodthread1+++2 testMethodthread1+++3 testMethodthread1+++4 testMethodthread1+++5 testMethodthread2---1 testMethodthread2---2 testMethodthread2---3 testMethodthread2---4 testMethodthread2---5 //很显然,无任何抢占,都是按照顺序执行,这就是公平锁的特点
3. ReentrantReadWriteLock
ReentrantLock类具有完全互斥排他的效果,同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务,这样虽然能够保证线程的安全,但是效率非常低下。
ReentrantReadWriteLock—读写锁,一个是读操作相关的锁,也称为共享锁;另一个是写操作相关的锁,也称排他锁。读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。可以提高程序的运行效率。
浙公网安备 33010602011771号