Oracle JDK 8 并发编程之锁和同步工具

发布时间:2024年01月05日

多线程编程是一项复杂的任务,需要开发者采取适当的同步机制来确保线程安全和提高程序性能。在Java中,锁和同步工具是实现多线程同步的关键组件。本博客将介绍一些常见的锁和同步工具,以及它们的用途和示例。

1. Synchronized锁

Synchronized是Java中最基本的同步机制,通过关键字synchronized可以保证在同一时间只有一个线程可以访问同步块。

示例

public class SynchronizedExample {
    private int sharedResource = 0;

    public synchronized void synchronizedMethod() {
        // 同步的代码块
        sharedResource++;
    }
}

在上面的示例中,synchronizedMethod方法使用synchronized关键字,确保对sharedResource的访问是线程安全的。

2. ReentrantLock锁

ReentrantLock提供了比synchronized更多的灵活性,允许实现可重入、定时锁等功能。

示例

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private int sharedResource = 0;
    private ReentrantLock lock = new ReentrantLock();

    public void someMethod() {
        lock.lock();
        try {
            // 临界区代码
            sharedResource++;
        } finally {
            lock.unlock();
        }
    }
}

在上述示例中,使用ReentrantLocklockunlock方法来确保线程安全。

3. Read/Write Lock(读写锁)

读写锁允许多个线程同时读取共享资源,但只允许一个线程写入。

示例

import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockExample {
    private int sharedResource = 0;
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public void readMethod() {
        ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
        readLock.lock();
        try {
            // 读取共享资源
        } finally {
            readLock.unlock();
        }
    }

    public void writeMethod() {
        ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
        writeLock.lock();
        try {
            // 写入共享资源
        } finally {
            writeLock.unlock();
        }
    }
}

在上面的示例中,readMethodwriteMethod方法分别使用读锁和写锁,实现了对共享资源的安全读写操作。

4. StampedLock锁

StampedLock提供了乐观读锁、悲观读锁和写锁,相对于ReentrantReadWriteLock更为灵活。

示例

import java.util.concurrent.locks.StampedLock;

public class StampedLockExample {
    private int sharedResource = 0;
    private StampedLock lock = new StampedLock();

    public void someMethod() {
        long stamp = lock.readLock();
        try {
            // 读取共享资源
            sharedResource++;
        } finally {
            lock.unlockRead(stamp);
        }
    }
}

在上述示例中,使用StampedLockreadLockunlockRead方法实现了乐观读锁。

5. Condition锁

Condition锁配合ReentrantLock使用,允许线程按条件等待和唤醒。

示例

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ConditionLockExample {
    private int sharedResource = 0;
    private ReentrantLock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void someMethod() throws InterruptedException {
        lock.lock();
        try {
            // 临界区代码
            condition.await(); // 等待条件满足
            // 或者 condition.signal(); 唤醒等待的线程
        } finally {
            lock.unlock();
        }
    }
}

上述示例中,Condition锁通过awaitsignal方法实现线程的等待和唤醒。

6. CountDownLatch锁

CountDownLatch允许一个或多个线程等待其他线程完成操作。

示例

import java.util.concurrent.CountDownLatch;

public class CountDownLatchExample {
    private CountDownLatch latch = new CountDownLatch(2); // 初始化计数器为2

    // 在两个线程中执行的操作
    public void someMethod() {
        try {
            // 执行一些操作
        } finally {
            latch.countDown(); // 操作完成,减少计数器
        }
    }

    // 在主线程中等待两个线程完成
    try {
        latch.await();
        // 主线程继续执行
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

在上述示例中,CountDownLatchcountDownawait方法用于实现线程的等待和计数。

7. CyclicBarrier锁

CyclicBarrier允许一组线程相互等待,直到所有线程都达到某个公共屏障点。

示例

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierExample {
    private CyclicBarrier barrier = new CyclicBarrier(3); // 初始化屏障点为3

    // 在三个线程中执行的操作
    public void someMethod() {
        try {
            // 执行一些操作
            barrier.await(); // 等待其他线程
        } catch (InterruptedException | BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}

在上述示例中,CyclicBarrierawait方法用于实现线程的等待,直到达到指定的屏障点。

8. Semaphore锁

Semaphore控制同时访问特定资源的线程数量。

示例

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    private Semaphore semaphore = new Semaphore(3); // 允许同时3个线程访问

    public void someMethod() {
        try {
            semaphore.acquire(); // 获取许可
            // 执行一些操作
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release(); // 释放许可
        }
    }
}

在上述示例中,Semaphoreacquirerelease方法用于控制线程的访问许可。

9. Exchanger锁

Exchanger允许两个线程在某个点交换对象。

示例

import java.util.concurrent.Exchanger;

public class ExchangerExample {
    private Exchanger<String> exchanger = new Exchanger<>();

    // 在两个线程中执行的操作
    public void someMethod() {
        try {
            String data = "Some data";
            String exchangedData = exchanger.exchange(data); // 交换对象
            // 处理交换后的对象
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

上述示例中,Exchangerexchange方法用于实现线程间的对象交换。

10. Phaser锁

Phaser提供更灵活的同步点,适用于一组线程协同工作。

示例

import java.util.concurrent.Phaser;

public class PhaserExample {
    private Phaser phaser = new Phaser();

    // 在多个线程中执行的操作
    public void someMethod() {
        phaser.register(); // 注册线程
        // 执行一些操作
        phaser.arriveAndAwaitAdvance(); // 到达同步点并等待其他线程
        // 继续执行
        phaser.arriveAndDeregister(); // 到达同步点并注销线程
    }
}

在上述示例中,PhaserregisterarriveAndAwaitAdvancearriveAndDeregister方法用于实现线程的注册、同步等待和注销。

结语

Java提供了丰富的锁和同步工具,开发者可以根据具体场景选择适当的工具来实现线程安全和提高程序性能。深入理解这些工具的使用方式对于编写高效、可靠的多线程程序至关重要。希望本博客能够帮助读者更好地理解Java中的锁和同步机制。

文章来源:https://blog.csdn.net/di101cipaqi/article/details/135349716
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。