Java并发编程实践

红尘紫陌 2020-03-08 ⋅ 19 阅读

在Java编程中,使用多线程可以提高程序的性能和响应能力。然而,多线程编程也带来了线程安全性等一系列问题。为了保证线程间的正确同步和协作,我们需要使用一些常见的多线程同步技巧。本文将介绍一些常见的Java多线程同步技巧,并提供一些示例代码。

1. synchronized关键字

synchronized关键字用于保护临界区,以确保同一时间只有一个线程能够访问临界资源。在方法级别使用synchronized关键字可以确保整个方法是线程安全的,也可以在代码块中使用synchronized关键字来同步特定的代码片段。

示例代码:

public class Counter {
    private int count = 0;

    // synchronized修饰方法
    public synchronized void increment() {
        count++;
    }

    // synchronized修饰代码块
    public void decrement() {
        synchronized (this) {
            count--;
        }
    }
}

2. volatile关键字

volatile关键字用于确保可见性和禁止指令重排。当一个变量被声明为volatile时,它的值将直接从主存中读取,而不是从线程的本地缓存中读取。

示例代码:

public class MyRunnable implements Runnable {
    private volatile boolean flag = true;

    public void run() {
        while (flag) {
            // do something
        }
    }

    public void stop() {
        flag = false;
    }
}

3. ReentrantLock

ReentrantLock是一个可重入的互斥锁,与synchronized关键字相比,它提供了更灵活的锁定方式。使用ReentrantLock可以通过调用lock()方法获取锁并通过调用unlock()方法释放锁。

示例代码:

import java.util.concurrent.locks.ReentrantLock;

public class Counter {
    private int count = 0;
    private ReentrantLock lock = new ReentrantLock();

    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

4. Condition

Condition接口提供了更高级的线程同步机制。它允许线程在满足特定条件时暂停执行(通过调用await()方法),并在条件变为真时恢复执行(通过调用signal()或signalAll()方法)。

示例代码:

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

public class MyBoundedBuffer<E> {
    private Object[] items;
    private int count;
    private int putIndex;
    private int takeIndex;

    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public void put(E item) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length) {
                notFull.await();
            }
            items[putIndex] = item;
            if (++putIndex == items.length) {
                putIndex = 0;
            }
            count++;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                notEmpty.await();
            }
            E item = (E) items[takeIndex];
            if (++takeIndex == items.length) {
                takeIndex = 0;
            }
            count--;
            notFull.signal();
            return item;
        } finally {
            lock.unlock();
        }
    }
}

5. ConcurrentHashMap

ConcurrentHashMap是Java中线程安全的哈希表实现。它通过将数据分割成多个片段来实现高并发性能,并使用锁分段技术来控制同一时间只有一个线程可以访问同一分段。

示例代码:

import java.util.concurrent.ConcurrentHashMap;

public class MyCache {
    private ConcurrentHashMap<String, Object> cache = new ConcurrentHashMap<>();

    public Object get(String key) {
        return cache.get(key);
    }

    public void put(String key, Object value) {
        cache.put(key, value);
    }

    public void remove(String key) {
        cache.remove(key);
    }
}

以上是一些常见的Java多线程同步技巧的示例代码。当编写多线程程序时,需要谨慎考虑线程安全性,并选择合适的同步机制来保证线程间的正确同步和协作。


全部评论: 0

    我有话说: