1. Lock接口
public interface Lock {}
- 提供更多实用性方法,功能更强大、性能更优越。
常用方法:
① void lock() // 获取锁,如锁被占用,则等待
② boolean trylock() // 尝试获取锁(成功true,失败false,不阻塞)
③ void unlock() // 释放锁
2. ReentrantLock类(重入锁/递归锁) - Lock接口实现类
public class ReentrantLock extends Object implements Lock, Serializable
- Lock接口的实现类,与synchronized一样具有互斥锁功能。
注意:
1)使用Lock,需要显式的获取锁和释放锁;
2)为了避免拿到锁的线程在运行期间出现异常,导致程序终止没有释放锁!应用try-finally来保证无论是否出现异常,最终必须释放锁;
3)ReentrantLock为重入锁,避免递归,如果必须递归,必须正确控制退出条件。
(此锁支持同一线程的2147483647个递归锁的最大值。试图在Error超过这个限制的结果将从锁定的方法。)
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestLocks {
public static void main(String[] args) {
Test obj = new Test();
Thread t1 = new Thread(new MyTask(obj));
Thread t2 = new Thread(new MyTask2(obj));
t1.start();
t2.start();
}
}
class Test{
Lock lock = new ReentrantLock(); // 可重入锁
public void method() {
System.out.println(Thread.currentThread().getName() + "进入上锁的方法中...");
try {
lock.lock(); // 获取锁(显式)
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//method(); //不要出现无穷递归,容易内存溢出导致锁一直没有释放。
System.out.println(Thread.currentThread().getName() + "退出上锁的方法中...");
} finally {
lock.unlock(); // 释放锁(显式) + 切记finally释放资源
}
}
}
class MyTask implements Runnable {
Test obj;
public MyTask(Test obj) {
super();
this.obj = obj;
}
@Override
public void run() {
obj.method();
}
}
class MyTask2 implements Runnable {
Test obj;
public MyTask2(Test obj) {
super();
this.obj = obj;
}
@Override
public void run() {
obj.method();
}
}
3. ReentrantReadWriteLock类(读写锁) - ReadWriteLock接口实现类
public class ReentrantReadWriteLock extends Object implements ReadWriteLock, Serializable
- 一种支持一写多读的同步锁,读写分离,可分别分配读锁、写锁;
- 支持多次分配读锁,使多个读操作可以并发执行(写锁同步,读锁异步)。
互斥规则:
① 写-写:互斥,阻塞;
② 读-写:互斥,读阻塞写、写阻塞读;
③ 读-读:不互斥、不阻塞;
- 在读操作远远高于写操作的环境下,可在保证线程安全的情况下,提高运行效率。
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
public class TestReadWriteLock {
public static void main(String[] args) {
Student s = new Student();
ExecutorService es = Executors.newFixedThreadPool(20);
WriteTask write = new WriteTask(s);
ReadTask read = new ReadTask(s);
long start = System.currentTimeMillis();
es.submit(write);
es.submit(write);
for (int i = 1; i <= 18; i++) {
es.submit(read);
}
es.shutdown();
while(true) {
System.out.println("结束了吗?");
if (es.isTerminated() == true) {
break;
}
}
long end = System.currentTimeMillis();
System.out.println("运行时间:" + (end-start));
}
}
class WriteTask implements Callable<Object> {
Student stu;
public WriteTask(Student stu) {
this.stu = stu;
}
@Override
public Object call() throws Exception {
this.stu.setAge(20);
return null;
}
}
class ReadTask implements Callable<Object> {
Student stu;
public ReadTask(Student stu) {
this.stu = stu;
}
@Override
public Object call() throws Exception {
this.stu.getAge();
return null;
}
}
class Student {
private int age;
//Lock lock = new ReentrantLock(); // 读写情况下都加锁,性能过低!
ReentrantReadWriteLock rrwl = new ReentrantReadWriteLock(); // 有两把锁
ReadLock read = rrwl.readLock(); // 读锁 - 内部类
WriteLock write = rrwl.writeLock(); // 写锁 - 内部类
// 赋值:写操作
public void setAge(int age) throws InterruptedException {
//lock.lock();
write.lock();
try {
Thread.sleep(1000);
this.age = age;
} finally {
//lock.unlock();
write.unlock();
}
}
// 取值:读操作
public int getAge() throws InterruptedException {
//lock.lock();
read.lock();
try {
Thread.sleep(1000);
return this.age;
} finally {
//lock.unlock();
read.lock();
}
}
}
// Lock互斥锁运行时间20034毫秒,ReadWriteLock读写锁运行时间3004毫秒