锁的几种应用场景

2026-01-08

首先嘛,最简单的就是单通道执行。【用synchronized加实例方法或类方法,synchronized(lock){}】

 

image

场景2:读和写并发进行(不加锁),但是修改是原子操作。用AtomicInteger等类实现

多线程访问的全局变量int就要用AtomicInteger  [低频竞争感觉不明显,高频竞争如果不用AtomicXXX就会出幽灵数字。即A在写它的时候,B也在写,最后出现了一个不是A也不是B的数字]

场景3:取号机制。秒杀时防止超卖。用CAS(其实是无锁机制)。拿到号就去下单,没拿到号(竞争失败)就返回失败。

@RestController
public class CASController {
    AtomicInteger store = new AtomicInteger(5);
    @GetMapping("/lock/cas/order") // 定义GET请求接口,路径为/hello
    public String set() throws InterruptedException {
        do{
            int s = store.get();
            if(s<=0){
                return "无库存了";
            }
            if(store.compareAndSet(s, s-1)){
                //这里处理下单逻辑
                return String.valueOf(s);
            }
            Thread.sleep(100);
        }while (true);
    }
}

 

场景4:写的时候,阻塞读。保证数据严格统一。即在写之前必须读的是旧数据,在写中或者说写后,读的必须是新数据。    没有写的时候,无锁读。

public class ReentrantLockTest {
    ReentrantLock lock = new ReentrantLock();
    AtomicInteger age = new AtomicInteger(100);
    public int read(){
        if(lock.isLocked()){
            lock.lock();
            try{
                return age.get();
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        return age.get();
    }
    public void write(int newAge){
        lock.lock();
        try{
            age.set(newAge);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }
}

 jdk原生是有支持类的:就是 ReentrantReadWriteLock

当写锁被持有(无论是否是当前线程)时,其他线程的读锁会被阻塞。ReentrantReadWriteLock 遵循 “读写互斥、写写互斥、读读共享” 的核心规则,写锁的独占性会直接阻塞后续的读操作请求。

场景5:生产者和消费者模式,当无资源消费时,就阻塞等待,直到有被生产者唤醒。

 

posted on 2026-01-08 14:22  angelshelter  阅读(1)  评论(0)    收藏  举报

导航