标签:ring val 提高 总结 unlock 简单 中断 pre ant
除了用Synchronized关键字修饰同步块,让线程获取某对象的锁实现多线程操作共享变量的同步外,还可以使用java.util.concurrent包。并且,juc包机制下的同步更灵活。juc包的所有锁都实现自Lock接口和ReadWriteLock接口,下面分别总结。
(图片来源于网络)
Lock接口
Lock在java.util.concurrent.locks包中,Lock是一个接口,我们一般使用的是它的实现类:ReentrantLock (可重入锁)。ReentrantLock类的主要方法有:
void lock() //获取调用此代码的对象的锁,失败就等待 boolean tryLock() //尝试获取调用此代码的对象的锁,失败返回false,不等待 boolean tryLock(long t) //尝试获取调用此代码的对象的锁,失败等待 t 时间后返回false void lockInterruptibly() // 获取调用此代码的对象的锁,失败就等待。但是这个等待可以中断 (与syn不同,syn只有wait、join、 sleep的线程可悲中断) void unlock() //释放锁(必须手动写明)
使用示例如下:
public class Main { public static void main(String[] args) { Test t = new Test(); t.readAndWriteSomething(); //main线程要对 t 进行一些需要同步的操作
}
}
class Test {
... int value = 1; Lock l = new ReentrantLock(); public void readAndWriteSomething() { l.lock(); //获取 t 的锁 .....; //从 t 读出写入一些内容 l.unlock(); //释放 t 的锁 } }
大概使用方法就是上面这样,至于其他的tryLock、lockInterruptibly等方法就看具体情况灵活应用了。但是手动释放锁的操作十分重要,不然其他线程可能会饥饿,甚至出现死锁现象。
ReadWriteLock接口
我们知道,多个线程读取并不会造成一些危险。所以我们想,可不可以有一种锁,在读操作的时候可以多个线程共享(即锁可以同时由几个线程共同持有),写操作时又变为互斥锁。ReadWriteLock接口的实现类ReentrantReadWriteLock可以实现这种操作。
ReentrantReadWriteLock中的两个方法:
Lock readLock() //返回一个读锁,时可以共享的 Lock writeLock() //返回一个写锁,不可以共享
使用示例:
public class Main { public static void main(String[] args) { Test t = new Test(); t.readAndWriteSomething(); //main线程要对 t 进行一些需要同步的操作
} } class Test { ... int value = 1; Lock l = new ReentrantReadWriteLock(); public void readAndWriteSomething() { l.readLock().lock(); //获取 t 的读锁 .....; //从 t 读出一些内容 l.readLock().unlock(); //释放 t 的读锁
l.writeLock().lock() //获取 t 的写锁 ...... //从 t 写入一些内容 l.writeLock().unlock(); //释放 t 的写锁 } }
可以看到,并没有多复杂,无非把一个对象的锁拆成读锁、写锁两部分而已,其中读锁是共享锁,写锁互是斥锁。读操作时获取读锁,写操作时获取写锁。提高效率
总结二者区别
Synchronized是关键字,lock机制是一组类实现;
Synchronized没有共享锁,lock机制有读锁(共享的);
Synchronized没有lock灵活,lock可以随时获取对象的锁,但需要手动释放(这也是灵活的表现);
lock机制下有tryLock返回获取锁的结果,成功or失败;
lock机制下获取锁失败的线程可以被中断。
当然,lock机制下,每个有同步块的对象需要持有实现了Lock接口的类的实例,通过这个实例去修改对象的锁状态。
标签:ring val 提高 总结 unlock 简单 中断 pre ant
原文地址:https://www.cnblogs.com/shen-qian/p/11218178.html