java ReentranLock锁

1、效果和synchronized一样,都可以同步执行,lock方法获得锁,unlock方法释放锁

使用示例:

package com.test;

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

public class MyService {

    private Lock lock = new ReentrantLock();
    public void methodA() {
        try {
            lock.lock();
            System.out.println("methodA begin ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println("methodA end ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void methodB() {
        try {
            lock.lock();
            System.out.println("methodB begin ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
            Thread.sleep(3000);
            System.out.println("methodB end ThreadName = " + Thread.currentThread().getName() + "time=" + System.currentTimeMillis());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
package com.test;

public class Run {

    public static void main(String[] args) {

        MyService myService = new MyService();
        Thread t1 = new Thread(new Runnable() {

            @Override
            public void run() {
                myService.methodA();
            }
        });
        Thread t2 = new Thread(new Runnable() {

            @Override
            public void run() {
                myService.methodB();
            }
        });
        t1.start();
        t2.start();
    }
}
结果:
methodA begin ThreadName = Thread-0time=1527821296840
methodA end ThreadName = Thread-0time=1527821299841
methodB begin ThreadName = Thread-1time=1527821299841
methodB end ThreadName = Thread-1time=1527821302841

注意:必须要在finally块里调用lock.unlock() 释放锁.

2、使用Condition实现等待/通知:

  awati() 与 signal() 方法:

  

package com.test;

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

public class MyService {

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

    public void testWait() {
        try {
            lock.lock();
            System.out.println("wait");
            condition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void testSignal() {
        try {
            lock.lock();
            condition.signal();
        } finally {
            lock.unlock();
        }
    }

}
  • 通过Condition对象来使线程wait,必须先执行lock.lock()获得锁。
  • Condition对象的signal()方法可以唤醒线程.
  • Condition的awati()方法和Object 中的wati()方法等效.
  • Condition的signal()方法和Object 中的notify()方法等效.
  • Condition的signalAll()方法和Object中的notifyAll()方法等效。

3、公平锁和非公平锁:

  公平锁标识线程获取锁的顺序是按照线程加锁的顺序来分配的。即先来先得的FIFO先进先出顺序。而非公平锁就是一种获取锁的抢占机制,是随机获得锁的。

  

Lock lock=new ReentrantLock(true);//公平锁
Lock lock=new ReentrantLock(false);//非公平锁

4、ReentrantLock 类的方法:

  • int getHoldCount() 的作用是查询当前线程保持此锁定的个数,也就是调用lock()方法的次数。
  • int getQueueLength()的所用是返回正在等待获取此锁的线程估计数 。比如有5个线程,1个线程首先执行await()方法,那么调用此方法的返回值是4.
  • int getWaitQueueLength(Condition condition)的所用是返回等待与此锁定相关的给定条件Condition的线程估计数,比如5个线程都执行了Condition的await()方法 ,那么返回值就是5.
  • boolean hasQueuedThreads()的作用是查询是否有线程正在等待获取此锁.
  • boolean hasWaiters(Condition condition)的作用是查询是否有线程正在等待与此锁定有关的condition条件。
  • boolean isFair()的作用是判断是不是公平锁.
  • boolean isHeldByCurrentThread()的作用是查询当前线程是否保持此锁。
  • boolean isLocked()的作用是查询此锁是否由任意线程保持。
  • void lockInterruptibly()的作用是:如果当前线程未被中断,则获取锁定,如果已经被中断则出现异常。
  • boolean tryLock()的作用是仅在调用时锁定未被另一个线程保持的情况下,才获取该锁定。
  • boolean tryLock(long timeout, TimeUnit unit) 的作用是,如果锁定在给定等待时间内没有被领一个线程保持,且当前线程未被中断,则获取该锁定。

5、ReentrantReadWriteLock 类,读写锁:

  类ReentrantLock 具有完全互斥排他的效果,即同一时间只有一个线程在执行lock()方法后面的任务。

  读写锁表示也有两个锁,一个是读操作相关的锁,也成为共享锁;另一个是写操作相关的锁,也就排它锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。在没有线程进行写操作时,进行读取操作的多个线程都可以获取读锁,而进行写入操作的线程只有在获取写锁后才能进行写入操作。即多个线程可以同时进行读操作,但同一时刻只有一个线程可以进行写操作。

  • 读读共享

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.readLock().lock();
                System.out.println("获取读锁:" + System.currentTimeMillis());
                Thread.sleep(1000);
            } finally {
                lock.readLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 写写互斥

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void write() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println("获取写锁:" + System.currentTimeMillis());
                Thread.sleep(1000);
            } finally {
                lock.writeLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 读写互斥

  

    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println("获取读锁:" + System.currentTimeMillis());
                Thread.sleep(1000);
            } finally {
                lock.writeLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void write() {
        try {
            try {
                lock.writeLock().lock();
                System.out.println("获取写锁:" + System.currentTimeMillis());
                Thread.sleep(1000);
            } finally {
                lock.writeLock().unlock();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

synchronized 和 lock 的用法区别:

  1. synchronized 是托管给JVM执行的。而Lock是Java写的控制锁的代码。
  2. synchronized 原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其他线程只能依靠阻塞来等待线程释放锁。而在CPU转换线程阻塞时会引起线程上下文切换,会导致效率很低。
  3. Lock用的是乐观锁方式。每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试。直到成功为止。
  4. ReentrantLock必须在finally中释放锁,而synchronized不需要。
  5. ReentrantLock提供了可轮询的锁请求,他可以尝试的去取得锁,如果取得成功则继续处理,取得不成功,可以等下次运行的时候处理,所以不容易产生死锁。而synchronized则一旦进入锁请求要么成功,要么一直阻塞,所以更容易产生死锁。
  6. synchronized的话,锁的范围是整个方法或synchronized块部分;而Lock因为是方法调用,可以跨方法,灵活性更大。

使用ReentrantLock的场景:

  1. 某个线程在等待一个锁的控制权的这段时间需要中断。
  2. 需要分开处理一些wait-notify,ReentrantLock里面的Condition应用,能够控制notify哪个线程.
  3. 具有公平锁功能,每个到来的线程都将排队等候.

原文地址:https://www.cnblogs.com/gouge/p/9120882.html

时间: 2024-10-28 14:15:25

java ReentranLock锁的相关文章

Java偏向锁实现原理(Biased Locking)

阅读本文的读者,需要对Java轻量级锁有一定的了解,知道lock record, mark word之类的名词.可以参考我的一篇博文:Java轻量级锁原理详解(Lightweight Locking) Java偏向锁(Biased Locking)是Java6引入的一项多线程优化.它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能. 轻量级锁也是一种多线程优化,它与偏向锁的区别在于,轻量级锁是通过CAS来避免进入开销较大的互斥操作,而偏向锁是在无竞争场景下完全消除同步,连CAS也不

synchronized与static synchronized 的差别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为例如以下部分: 第一部分:synchronized与static synchronized 的差别 第二部分:JVM底层又是怎样实现synchronized的 第三部分:Java多线程锁,源码剖析 第一部分:synchronized与static synchronized的差别 1.synchronized与static synchronized 的差别 synchronized是对类的当前实例进行加锁,防止其它线程同一时候訪问该类的该实例的全部synchronized块.注意这里

java 同步锁(synchronized)

java 同步锁(synchronized) 在java中,Synchronized就是一把锁,他可以锁定一个方法,也可以锁定一个方法,我擦,其实这两个东西就是一样的.块不就是一个没有名字的方法么,方法就是一个有名字的块.本文就用块来测试.所谓锁,就是原子操作,把这个锁定的块作为一个整体,就像你上厕所,拉了就要擦屁屁,当然你也可以不擦,如果你不在意出现的问题的话.信号量Semaphore和这个Synchronized 其实实现的功能差不多,不过效率不同,使用的方式也不同.Synchronized

java的锁机制

一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中). 取到锁后,他就开始执行同步代码(被synchronized修饰的代码):线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中等待的某个线程就可以拿到锁执行同步代码了.这样就保证了同步代码在统一时刻只有一个线程在执行. 众所周知,在Java多线程编程中

synchronized与static synchronized 的区别、synchronized在JVM底层的实现原理及Java多线程锁理解

本Blog分为如下部分: 第一部分:synchronized与static synchronized 的区别 第二部分:JVM底层又是如何实现synchronized的 第三部分:Java多线程锁,源代码剖析 第一部分:synchronized与static synchronized的区别 1.synchronized与static synchronized 的区别 synchronized是对类的当前实例进行加锁,防止其他线程同时访问该类的该实例的所有synchronized块,注意这里是"类

java的锁机制——synchronized

转自:http://blog.csdn.net/yangzhijun_cau/article/details/6432216 一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中). 取到锁后,他就开始执行同步代码(被synchronized修饰的代码):线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中

[置顶] 深入探析Java线程锁机制

今天在iteye上提了一个关于++操作和线程安全的问题,一位朋友的回答一言点醒梦中人,至此我对Java线程锁有了更加深刻的认识.在这里也做个总结供大家参考. 先看几段代码吧! 代码一: [java] view plaincopy public class TestMultiThread2 implements Runnable{ private static Object o = new Object(); private static Integer si = 0; private stati

java中锁机制

一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线程)就只能等了(线程阻塞在锁池等待队列中). 取到锁后,他就开始执行同步代码(被synchronized修饰的代码):线程执行完同步代码后马上就把锁还给同步对象,其他在锁池中等待的某个线程就可以拿到锁执行同步代码了.这样就保证了同步代码在统一时刻只有一个线程在执行.   众所周知,在Java多线程编

java 对象锁和类锁的区别(转)

java 对象锁和类锁的区别   转自 <http://zhh9106.iteye.com/blog/2151791> 在java编程中,经常需要用到同步,而用得最多的也许是synchronized关键字了,下面看看这个关键字的用法. 因为synchronized关键字涉及到锁的概念,所以先来了解一些相关的锁知识. java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途