Java并发编程中的锁

时间:2021-06-30 21:08:36   收藏:0   阅读:15

synchronized

使用synchronized实现同步有2种方式:

任何Java对象均可作为锁使用,其中,使用的锁对象有以下3种:

同步方法

private synchronized void f()
{
    //...
}    

同步代码块

private void f()
{
    synchronized(this)
    {
        //...
    }
}

Lock

Lock接口中规定了锁必须实现的一些方法

Lock接口的实现类有ReentarntLockReentrantReadWriteLock2种,它们都提供了非公平锁和公平锁2种形式。

ReentrantLock

可重入锁,线程可以重复的获取已经持有的锁。
锁中维护着一个持有计数,来追踪对lock方法的嵌套调用,每次lock计数加1,每次unlock计数减1。
只有持有计数为0时,才释放锁。

使用示例

private Lock lock=new ReentrantLock();

private void f()
{
    lock.lock();
    try
    {
        // ...
    }
    finally
    {
        lock.unlock();
    }
}

公平锁,线程调度器将优先(并不保证一定)执行等待时间最长的线程。

在创建ReentrantLock时,可以传入Boolean参数true,创建一个公平锁。

Lock fairLock=new ReentrantLock(true);

除了使用lock()获取锁外,还可以使用tryLock()尝试获取锁,如果成功,返回true,否则,返回false,并且线程可以立即离开去做其它事情。
还可以调用传入超时参数。

ReentrantReadWriteLock

可重入读写锁。如果对一个数据结构进行读操作的次数远远大于写操作的次数,就可以使用读写锁提高性能。

使用示例

private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();// 创建读写锁
private Lock readLock=lock.readLock();// 读锁
private Lock writeLock=lock.writeLock();// 写锁

// 读操作加读锁
public void read()
{
    readLock.lock();
    try
    {
        // ...
    }
    finally
    {
        readLock.unlock();
    }
}

// 写操作加写锁
public void write()
{
    writeLock.lock();
    try
    {
        // ...
    }
    finally
    {
        writeLock.unlock();
    }
}

死锁

死锁问题的产生,是由于线程A和线程B互相持有对方需要获取的锁对象导致的

private static final Object lockA=new Object();
private static final Object lockB=new Object();

private void deadLock()
{
    Thread t1=new Thread(()->{
        synchronized(lockA)
        {
            sleep(1L);
            synchronized(lockB)
            {
                System.out.println("thread 1");
            }
        }
    });

    Thread t2=new Thread(()->{
        synchronized(lockB)
        {
            sleep(1L);
            synchronized(lockA)
            {
                System.out.println("thread 2");
            }
        }
    });

    t1.start();
    t2.start();
}

private void sleep(long timeout)
{
    try
    {
        TimeUnit.SECONDS.sleep(timeout);
    }
    catch(InterruptedException e)
    {
        e.printStackTrace();
    }
}

死锁问题一旦发生,程序就会挂起。所以,必须避免死锁的发生,有以下几个方式

原文:https://www.cnblogs.com/lypzzzzz/p/14955999.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!