Java案例如何实现同步锁机制?

wen java案例 17

本文目录导读:

Java案例如何实现同步锁机制?

  1. synchronized 关键字
  2. Lock 接口及其实现
  3. 高级同步工具
  4. 最佳实践建议
  5. 注意事项

在Java中实现同步锁机制主要有以下几种方式,我会从简单到复杂逐一说明,并提供实际案例。

synchronized 关键字

方法级别的同步

public class Counter {
    private int count = 0;
    // 同步实例方法
    public synchronized void increment() {
        count++;
    }
    // 同步静态方法(锁住整个类)
    public static synchronized void staticMethod() {
        // 静态方法同步
    }
}

代码块级别的同步

public class BankAccount {
    private double balance = 0;
    private final Object lock = new Object(); // 专门的锁对象
    public void deposit(double amount) {
        synchronized (lock) {
            balance += amount;
            System.out.println("存款后余额: " + balance);
        }
    }
    public void withdraw(double amount) {
        synchronized (lock) {
            if (balance >= amount) {
                balance -= amount;
                System.out.println("取款后余额: " + balance);
            }
        }
    }
}

实际案例:线程安全的计数器

public class ThreadSafeCounter {
    private int count = 0;
    public void increment() {
        synchronized (this) {
            count++;
            System.out.println(Thread.currentThread().getName() + " 计数: " + count);
        }
    }
    public static void main(String[] args) {
        ThreadSafeCounter counter = new ThreadSafeCounter();
        // 创建10个线程同时计数
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                for (int j = 0; j < 100; j++) {
                    counter.increment();
                }
            }, "线程-" + i).start();
        }
    }
}

Lock 接口及其实现

使用 ReentrantLock

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ReentrantLockExample {
    private final Lock lock = new ReentrantLock();
    private int sharedResource = 0;
    public void accessResource() {
        lock.lock(); // 获取锁
        try {
            sharedResource++;
            System.out.println(Thread.currentThread().getName() + " 访问资源: " + sharedResource);
        } finally {
            lock.unlock(); // 确保释放锁
        }
    }
    // 可中断的锁获取
    public void interruptibleAccess() throws InterruptedException {
        if (lock.tryLock(1, TimeUnit.SECONDS)) {
            try {
                System.out.println("获取锁成功,执行操作");
            } finally {
                lock.unlock();
            }
        } else {
            System.out.println("获取锁超时");
        }
    }
}

读写锁案例

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockExample {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private Map<String, String> cache = new HashMap<>();
    public String get(String key) {
        readLock.lock(); // 读锁,可多个线程同时读
        try {
            return cache.get(key);
        } finally {
            readLock.unlock();
        }
    }
    public void put(String key, String value) {
        writeLock.lock(); // 写锁,独占
        try {
            cache.put(key, value);
        } finally {
            writeLock.unlock();
        }
    }
}

高级同步工具

CountDownLatch(倒计时闩锁)

import java.util.concurrent.CountDownLatch;
public class CountDownLatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);
        // 创建3个工作线程
        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 完成任务");
                latch.countDown(); // 计数器减1
            }, "工作线程-" + i).start();
        }
        latch.await(); // 等待所有线程完成
        System.out.println("所有任务完成,继续执行主线程");
    }
}

Semaphore(信号量)

import java.util.concurrent.Semaphore;
public class SemaphoreExample {
    private final Semaphore semaphore = new Semaphore(3); // 允许3个线程同时访问
    public void accessResource() {
        try {
            semaphore.acquire(); // 获取许可
            System.out.println(Thread.currentThread().getName() + " 访问资源");
            Thread.sleep(1000); // 模拟资源访问
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            semaphore.release(); // 释放许可
        }
    }
}

最佳实践建议

选择合适的同步方式

public class SynchronizationBestPractice {
    // 1. 简单的同步使用 synchronized
    private int simpleCounter = 0;
    public synchronized void increment() {
        simpleCounter++;
    }
    // 2. 需要高级功能时使用 Lock
    private final ReentrantLock lock = new ReentrantLock(true); // 公平锁
    public void complexOperation() {
        lock.lock();
        try {
            // 需要超时、可中断等高级功能
        } finally {
            lock.unlock();
        }
    }
    // 3. 读多写少场景使用读写锁
    private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    // 4. 避免死锁:按固定顺序获取锁
    private final Object lock1 = new Object();
    private final Object lock2 = new Object();
    public void avoidDeadlock() {
        synchronized (lock1) {
            synchronized (lock2) {
                // 始终先获取 lock1,再获取 lock2
            }
        }
    }
}

注意事项

  1. 粒度控制:同步块的范围要尽可能小,只保护必要的共享资源
  2. 避免死锁:多个锁时要保持一致的获取顺序
  3. 使用finally释放锁:Lock接口必须在finally块中释放锁
  4. 性能考虑
    • synchronized 适合简单场景
    • ReentrantLock 提供更灵活的锁机制
    • ReadWriteLock 适合读多写少场景

选择哪种同步机制取决于具体的业务需求、性能要求和代码复杂度,简单的计数器使用 synchronized,复杂的高并发场景考虑 Lock 接口和并发工具类。

抱歉,评论功能暂时关闭!