java并发编程 之 Lock(锁的妙用)

本文深入探讨Java 5中引入的Lock机制,包括互斥锁ReentrantLock与读写锁ReentrantReadWriteLock的使用方法及优势。通过具体示例说明如何利用读写锁提升多线程环境下读操作的并发性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java 5中提供了另一种实现线程同步或互斥的机制,即使用Lock。Lock比传统线程模型中的synchronized方式更加面向对象。
互斥锁–Lock(ReentrantLock)
所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别:
synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是隐式的, 只要线程运行的代码超出了synchronized语句块范围, 锁就会被释放. 而Lock机制必须显式的调用Lock对象的unlock()方法才能释放锁, 这为获取锁和释放锁不出现在同一个块结构中, 以及以更自由的顺序释放锁提供了可能。

读写锁–ReadWriteLock(ReentrantReadWriteLock)
读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,写锁与写锁互斥。换句话说读取锁允许多个reader线程同时持有, 而写入锁最多只能有一个writter线程持有。
读写锁的使用场合: 读取共享数据的频率远大于修改共享数据的频率, 在上述场合下, 使用读写锁控制共享资源的访问, 可以提高并发性能。

package com.huang.test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * 读写锁的妙用
 * 简单缓存 的原理
 * @author wuseyukui
 *
 */
public class CacheDemo {

    private ReadWriteLock lock = new ReentrantReadWriteLock();

    private Map<String, Object> cache = new HashMap<String, Object>();

    public static void main(String[] args) {

    }

    /**
     * 简单,通俗
     * 缺点:只有写的时候需要同步(互斥),多线程读数据的时候不需要同步,影响效率
     * @param key
     * @return
     */
//  public synchronized Object getData(String key) {
//       Object obj = cache.get(key);
//       if (obj == null) {
//           obj = "aaa";// 实际是去查询DB
//       }
//      
//      return obj;
//  }

    /**
     * 效率高, 多线程读数据时用读锁可并发,写数据时用写锁互斥。
     * @param key
     * @return
     */
    public synchronized Object getData(String key) {
         lock.readLock().lock();
         Object obj = null;
         try {
            obj = cache.get(key);
             if (obj == null) {
                 lock.readLock().unlock();
                 lock.writeLock().lock();// ①
                 try {
                     // 为了代码的严禁缜密
                     // 假设有三个线程到了代码①处,线程1成功获得写锁,另外两个线程被阻塞。
                     // 当线程1执行到②,释放了写锁,另外两个线程就有机会获取到写锁,进行DB操作,此时obj已经不为空,不需要再查询DB
                     if (obj == null) {
                         obj = "aaa";// 实际是去查询DB
                     }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.writeLock().unlock();// ②
                }
                 lock.readLock().lock();
             }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.readLock().unlock();
        }
        return obj;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值