📜  Java的锁框架与线程同步(1)

📅  最后修改于: 2023-12-03 15:32:04.890000             🧑  作者: Mango

Java的锁框架与线程同步

Java中的锁框架是多线程编程中的重要概念,用于解决线程同步问题,以保证多线程执行时的数据一致性与安全性。其主要通过锁对象的概念来实现对线程同步的掌控。

基本概念
锁对象

Java中的锁对象是用于同步线程的共享资源,常见的锁对象包括synchronized、ReentrantLock等。

synchronized

synchronized是Java中最基本的锁对象,其可以用来修饰方法或者代码块。在Java中每个对象都有一个内部锁(也称为Monitor),可以通过synchronized关键字来获取该锁,保证同一时间只有一个线程可以进入被锁定的代码块。以下为synchronized的使用实例:

public synchronized void method() {
    //synchronized修饰方法
    //...
}

public void method1(){
    synchronized(this){
        //synchronized修饰代码块
        //...
    }
}
ReentrantLock

ReentrantLock是Java中比synchronized更灵活的锁对象,其可以控制锁的获取与释放,提供了更多的锁操作功能,比如可重入、公平锁、读写锁等,使用ReentrantLock时必须记得在死亡前释放锁,否则可能会导致死锁。以下为ReentrantLock的使用实例:

ReentrantLock lock = new ReentrantLock();//创建一个ReentrantLock对象
lock.lock();//获取锁
try {
    //...
} finally {
    lock.unlock();//释放锁
}

ReentrantLock fairLock = new ReentrantLock(true);//创建一个公平锁
fairLock.lock();
try {
    //...
} finally {
    fairLock.unlock();
}
常见使用场景
线程安全的集合类

Java提供了线程安全的集合类,比如Vector、Hashtable、ConcurrentHashMap等。这些类内部都使用了锁对象来保证数据安全性。

//使用线程安全的Vector
Vector<String> vector = new Vector<>();
vector.add("1");
vector.add("2");
vector.add("3");

//使用线程安全的Hashtable
Hashtable<String,String> hashtable = new Hashtable<>();
hashtable.put("1","value1");
hashtable.put("2","value2");
hashtable.put("3","value3");

//使用线程安全的ConcurrentHashMap
ConcurrentMap<String,String> concurrentMap = new ConcurrentHashMap<>();
concurrentMap.put("1","value1");
concurrentMap.put("2","value2");
concurrentMap.put("3","value3");
线程池

线程池是Java中常见的多线程编程方式,其内部使用到了锁对象来控制并发。

ExecutorService executorService = Executors.newFixedThreadPool(10);//创建一个线程池
executorService.execute(new Runnable() {
    @Override
    public void run() {
        //...
    }
});
executorService.shutdown();//关闭线程池
死锁

死锁是多线程编程中最常见的问题之一,其发生的原因是线程之间互相等待对方释放资源,从而导致线程无法继续执行。为了避免死锁的发生,可以在获取锁的时候添加一个超时时间,如果在规定时间内没有获取到锁,则释放锁。

Lock lock1 = new ReentrantLock();
Lock lock2 = new ReentrantLock();

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        lock1.lock();
        try {
            Thread.sleep(500);
            lock2.lock();
            //...
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock1.unlock();
            lock2.unlock();
        }
    }
});

Thread t2 = new Thread(new Runnable() {
    @Override
    public void run() {
        lock2.lock();
        try {
            Thread.sleep(500);
            if(lock1.tryLock(500,TimeUnit.MILLISECONDS)){
                //...
            }else{
                //...
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock2.unlock();
            if(lock1.isHeldByCurrentThread()){
                lock1.unlock();
            }
        }
    }
});

t1.start();
t2.start();
总结

锁框架是Java多线程编程中非常重要的概念,可以使用synchronized、ReentrantLock等锁对象来实现线程同步,以保证多线程执行时的数据一致性与安全性。在使用锁对象时,需要注意死锁问题,并根据具体业务场景选择不同的锁对象以及不同的锁操作方式。