java锁_Java锁

java锁

锁是一种线程同步机制,例如同步块。 锁是使用同步块在内部实现的。 因此,我们可以在Java中使用锁代替同步关键字。 锁比同步块更灵活,更复杂。

从Java 5版本开始,JDK提供了几种锁实现,例如ReentrantReadWriteLock,ReentrantLock和StampedLock等。

1.同步和锁之间的区别

1)我们可以设置一个超时来使用Lock.tryLock(long timeout,TimeUnit timeUnit)方法访问资源,而同步是不可能的。

2)同步块必须完全包含在一个进程中。 锁可以包含在两个单独的进程中:lock()和unlock()。

3)处于“等待”状态以获取对同步块的访问权限的线程不能被中断。 Lock API提供了方法lockInterruptible(),该方法可在线程等待Lock时中断线程。

2.实现简单锁:

使用synced关键字可以实现简单的增量功能。

public class Counter {

            private int number = 0;

            public void increment() {

                        synchronized(number) {

                                    return ++number;

                        }
            }
}

让我们使用Lock接口转换上述程序。

public class Counter {

            private int number = 0;

            private Lock lock = new Lock();

            public void increment() {                   

                        lock.lock();

                        int newNumber  = ++number;

                        lock.unlock();

                        return new number;
            }
}

在这里,我们使用的是锁接口,而不是synced关键字。

在增加数字之前,我们必须先锁定,以便其他任何人都不能在该块中输入任何内容,直到锁定增加并释放为止。

3.改进代码的方法

假设有些线程正在读取数据,有些线程正在向某些资源写入日期。 对于读取线程,如果一个线程正在从资源中读取数据,如果另一个线程也在从资源中读取数据,则不会造成任何问题,但是如果一个线程正在向资源中写入数据,则另一个线程也正在向资源中写入数据,则会引起问题。

  • 对于读取操作,可以允许多个线程从资源读取数据,但不允许写入线程。
  • 如果请求一个线程进行读取访问,而请求一个线程进行写入访问,那么优先级是什么,哪个线程可以访问资源?
  • 如果请求一个线程进行读取访问,则请求第二个线程进行写入访问,如果请求读取访问的线程更多,则如果我们仅允许读取请求的线程,则写入线程将需要等待不确定的时间,这导致饥饿。
  • 为了避免出现这种情况,Java在读取访问和写入访问时设置了一些规则。

3.1 ReadWriteLock

ReadWriteLock是Java 5版本中Java提供的实现; 它有两种方法,分别是Lock()和write-lock()。

Read Lock方法用于读取操作,而write-lock()方法用于写入操作。

3.2锁入

Java中的同步块是可重入的。 如果Java线程输入了同步的代码块,请在同步块的监视器对象上使用Lock。 然后,线程可以输入在同一监视对象上同步的其他Java代码块。

4.让我们考虑以下情形:

  1. Thread1正在获得读取访问权限。
  2. Thread2正在请求写访问权限; 由于只有一个阅读器,因此它将被阻止。
  3. 线程1再次请求读取访问权限,因为有一个写入请求,它将被阻止。

线程1和线程2都将被阻塞,从而导致死锁情况。

为了使锁重入,Java提供了另一种锁实现。

在使用重入锁定时,我们需要了解一些用例,例如,

在同一对象上,在某些方法中,线程可能会请求读取访问权限;在同一对象上,可能是线程在不同方法中,可能会请求写访问权限,反之亦然。

4.1阅读重入:

如果线程可以获取读访问权限(无写访问权限和写请求),或者该线程已经具有读访问权限,则该线程将被授予重入权限。 (无论是否有书面要求)。

4.2写重入:

仅当他们必须具有写访问权限时,才授予写重入权限。

4.3读写入口:

有时,线程必须同时读取和写入访问权限。 为此,线程必须是唯一的读取器。

4.4写读入口:

有时,必须具有写访问权的线程也需要读访问权。 如果有要求,应始终授予写者读访问权限。 如果该线程具有读取访问权限,则其他任何线程都不能具有读取或写入访问权限,因此这并不危险。

基于以上概念,让我们实现ArrayList的同步版本。

ThreadSaftyArrayList.java

public class ThreadSaftyArrayList {

       private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

       private final Lock writeLock = readWriteLock.writeLock();

       private final Lock readLock = readWriteLock.readLock();

       private List list = new ArrayList();

       public E get(int index)

       {

              readLock.lock();

              try {               

                     return list.get(index);

              } finally {

                     readLock.unlock();

              }

       }

       public void set(E e)

       {

              writeLock.lock();

              try {

                     list.add(e);

              } finally {

                     writeLock.unlock();

              }

       }

       public static void main(String[] args)

    {

              ThreadSaftyArrayList threadSafeArrayList = new ThreadSaftyArrayList();

         threadSafeArrayList.set("1");

         threadSafeArrayList.set("2");

         threadSafeArrayList.set("3");

        System.out.println("Printing the First Element : "+threadSafeArrayList.get(1));

    }
}

注意:从最后一个子句中调用解锁():

当使用ReadWriteLock保护关键部分并且关键部分可能会引发异常时,从finally子句内部调用readUnlock()和writeUnlock()方法很重要。 这样做可以确保ReadWriteLock已解锁,以便其他线程可以锁定它。

伪代码:

lock.lockWrite();

try{

  //do critical section code, which may throw an exception

} finally {

  lock.unlockWrite();

}

5.结论

在当前的博客中,我们了解了锁,如何在Java中实现锁,如何替换了同步块。 我们还了解了不同类型的锁,例如读取锁和写入锁。 我们了解了Starvation(何时发生)以及Reentrance锁,它的用途以及Java中提供的实现类。 最后,我们使用ReentrantReadWriteLock类编写了示例ThreadSafty Arraylist类。 希望以上教程对Java开发人员和社区有所帮助。

6.下载Java中的锁

这是Java中的锁的示例。

下载
您可以在此处下载此示例的完整源代码: Java中的Locks

翻译自: https://www.javacodegeeks.com/locks-in-java.html

java锁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值