java 锁

  • 锁的种类
1 重入锁(ReentrantLock)
入这里指的是在某线程已经获取锁之后,该线程可以再次获取锁,进入同步代码块。
这里需要强调一下重入的概念中所指的线程是已经获得锁的的线程,这与线程安全不冲突
以下列出了synchronized与ReentrantLock的不同之处:
a ReentrantLock提供了显式加解锁操作。提供了lock(),unlock()方法进行加解锁的操作,而synchronized是隐式进行加锁与解锁操作(依赖于编译器将其编译为moniterenter与moniterexit)。
b 对锁的等待可以中断,在持有锁的线程长时间不释放锁时,等待锁的线程可以选择放弃等待,这样就避免了synchronized可能带来的死锁问题。ReentrantLock.tryLock()可以设置等待时间.
c ReentrantLock提供了公平锁与非公平锁,而synchronized的实现是非公平锁。

** 注意**
ReentrantLock相对于synchronized来说一般用于,加锁与解锁操作需要分离的使用场景,
例如加解锁不再一个函数里(synchronized无法用括号包围),相对来说ReentrantLock提供了更高的灵活性
,但是使用时一定不要忘了释放锁。
2 读写锁(ReentrantReadWriteLock)
a 在没有写操作线程获取写锁的情况下,所有读操作都可以获取读锁。
b 在有写线程获取写锁的情况下,读操作等待写线程释放锁后,才可以获取读锁
c 在有读线程获取读锁的情况下,写线程会等待所有读线程释放锁后,才可以获取写锁,并且与此同时,所有的读锁也不可获取。

实例:
public class ReentrantReadWriteLockHashMap {
    private final Map hashMap = new HashMap();
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    public final void put(String key, Object value){
        //上写锁,不允许其他线程读也不允许写
        writeLock.lock();
        hashMap.put(key, value);
        writeLock.unlock();
    }
    public final Object get( String key ){
        //上读锁,其他线程只能读不能写
        readLock.lock();
        Object value =  hashMap.get(key);
        readLock.unlock();
        return value;
    }
}

3 volatile: 轻量级的线程操作可见方式

如果是多写场景,一定会出现线程安全问题
如果是一写多读的方式,则使用volatile非常合适,在实际中如果不能判断是否是一写多读的场景,一定要为加锁。

4 synchronized
关键词:synchronized 对象监控器 阻塞队列

参考
1 面试16解析-深挖锁

你可能感兴趣的:(java 锁)