java同步:Lock
来源:互联网 发布:美工算平面设计吗 编辑:程序博客网 时间:2024/05/22 06:41
一、Lock与synchronized的比较
二、Java.util.concurrent.locks包下的两个接口
Lock接口是一个通用接口,定义了对同步操作的基本方法public interface Lock { void lock(); void lockInterruptibly() throws InterruptedException; boolean tryLock(); boolean tryLock(long time, TimeUnit unit) throws InterruptedException; void unlock(); }
unlock()是用来释放锁的。
四个获取锁方法的区别:
1)、lock()方法:lock()方法是平常用的最多的方法,就是用来获取锁,如果锁已被其他线程获取,则进行等待。
注意:如果采用Lock方式,必须主动去释放锁,如果发生了异常,Lock方式是不会自动释放锁的。因此,一般来说,使用Lock必须在try{}catch(e){}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被释放,防止死锁的发生。
2)、tryLock()方法:tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,若获取失败(即锁已被其他线程获取),则返回false,也就是说,这个方法无论如何都会立即返回,在拿不到锁时不会一直在那儿等待。
3)、tryLock(Long time,TimeUnit unit)方法与tryLock()方法是类似的,只不过区别在于这个方法在拿不到锁时会等待time指定的时间,在time时间之后,如果还拿不到锁,则返回false。如果一开始或在等待期间拿到了锁,则返回true。
4)、lockInterruptibly()方法比较特殊,当通过这个方法去获取锁时,如果线程正在等待获取锁时,则这个线程能够响应中断,即中断线程的等待状态。也就是说,当两个线程同时通过lock.lockInterruptibly()想获取某个锁时,假如此时线程A获取到了锁,线程B只有等待,那么线程B能够调用threadB.interrupt()方法能够中断线程B的等待过程。
注意:当一个线程获取了锁,是不会被interrupt方法中断的。
因此,通过lock.lockInterruptibly()方法获取某个锁时,如果不能获取到,只有进行等待的情况下,是可以响应中断的。
而用synchronized关键字进行修饰的话,当线程处于等待某个锁的状态下,是无法被中断啊的,只有一致等待下去。
定义了如何获取读锁以及写锁的方法,也就是该接口将文件的读写操作分开,分成两个锁分配给线程,从而使多个线程可以同时进行读操作。定义的基本方法如下:public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading. */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing. */ Lock writeLock();}
三、ReentrantLock类
1、lock()方法的使用:public class MyLockTest {private static ArrayList<Integer> arrayList = new ArrayList<Integer>();static Lock lock = new ReentrantLock(); // 注意这个地方public static <E> void main(String[] args) {new Thread() {public void run() {Thread thread = Thread.currentThread();lock.lock();try {System.out.println(thread.getName() + "得到了锁");for (int i = 0; i < 5; i++) {arrayList.add(i);}} catch (Exception e) {// TODO: handle exception} finally {System.out.println(thread.getName() + "释放了锁");lock.unlock();}};}.start();new Thread() {public void run() {Thread thread = Thread.currentThread();lock.lock();try {System.out.println(thread.getName() + "得到了锁");for (int i = 0; i < 5; i++) {arrayList.add(i);}} catch (Exception e) {// TODO: handle exception} finally {System.out.println(thread.getName() + "释放了锁");lock.unlock();}};}.start();}}2、tryLock()方法的使用:/** * 观察现象:一个线程获得锁后,另一个线程取不到锁,不会一直等待 * @author * */public class MyTryLock {private static ArrayList<Integer> arrayList = new ArrayList<Integer>();static Lock lock = new ReentrantLock(); // 注意这个地方public static void main(String[] args) {new Thread() {public void run() {Thread thread = Thread.currentThread();boolean tryLock = lock.tryLock();System.out.println(thread.getName()+" "+tryLock);if (tryLock) {try {System.out.println(thread.getName() + "得到了锁");for (int i = 0; i < 5; i++) {arrayList.add(i);}} catch (Exception e) {// TODO: handle exception} finally {System.out.println(thread.getName() + "释放了锁");lock.unlock();}}};}.start();new Thread() {public void run() {Thread thread = Thread.currentThread();boolean tryLock = lock.tryLock();System.out.println(thread.getName()+" "+tryLock);if (tryLock) {try {System.out.println(thread.getName() + "得到了锁");for (int i = 0; i < 5; i++) {arrayList.add(i);}} catch (Exception e) {// TODO: handle exception} finally {System.out.println(thread.getName() + "释放了锁");lock.unlock();}}};}.start();}}3、lockInterruptibly()响应中断的方法的使用:
/** * 观察现象:如果thread-0得到了锁,阻塞。。。thread-1尝试获取锁,如果拿不到,则可以被中断等待 * @author * */public class MyInterruptibly { private Lock lock = new ReentrantLock(); public static void main(String[] args) { MyInterruptibly test = new MyInterruptibly(); MyThread thread0 = new MyThread(test); MyThread thread1 = new MyThread(test); thread0.start(); thread1.start(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } thread1.interrupt(); System.out.println("====================="); } public void insert(Thread thread) throws InterruptedException{ lock.lockInterruptibly(); //注意,如果需要正确中断等待锁的线程,必须将获取锁放在外面,然后将InterruptedException抛出 try { System.out.println(thread.getName()+"得到了锁"); long startTime = System.currentTimeMillis(); for( ; ;) { if(System.currentTimeMillis() - startTime >= Integer.MAX_VALUE) break; //插入数据 } } finally { System.out.println(Thread.currentThread().getName()+"执行finally"); lock.unlock(); System.out.println(thread.getName()+"释放了锁"); } }} class MyThread extends Thread { private MyInterruptibly test = null; public MyThread(MyInterruptibly test) { this.test = test; } @Override public void run() { try { test.insert(Thread.currentThread()); } catch (Exception e) { System.out.println(Thread.currentThread().getName()+"被中断"); } }}
四、ReentrantReadWriteLock类:
1)、readLock(),用来获取读锁2)、writeLock(),用来获取写锁
假如有多个线程进行读操作时,synchronized与ReentrantReadWriteLock方式比较:
1、synchronized方式:
** * 一个线程又要读又要写,用synchronize来实现的话,读写操作都只能锁住后一个线程一个线程地进行 * @author * */public class MySynchronizedReadWrite { public static void main(String[] args) { final MySynchronizedReadWrite test = new MySynchronizedReadWrite(); new Thread(){ public void run() { test.get(Thread.currentThread()); }; }.start(); new Thread(){ public void run() { test.get(Thread.currentThread()); }; }.start(); } public synchronized void get(Thread thread) { long start = System.currentTimeMillis(); int i=0; while(System.currentTimeMillis() - start <= 1) { i++; if(i%4==0){ System.out.println(thread.getName()+"正在进行写操作"); }else { System.out.println(thread.getName()+"正在进行读操作");} } System.out.println(thread.getName()+"读写操作完毕"); }}运行结果:。。。Thread-0正在进行读操作Thread-0正在进行读操作Thread-0正在进行读操作Thread-0正在进行写操作Thread-0读写操作完毕Thread-1正在进行读操作Thread-1正在进行读操作Thread-1正在进行读操作。。。结果分析:不管运行多少次,都是同样的结果,不管是读操作还是写操作,当一个线程获取锁并执行,另一个线程只有等待,当前线程执行完成后,等待线程才能执行,2、ReentrantReadWriteLock方式:
/** * 使用读写锁,可以实现读写分离锁定,读操作并发进行,写操作锁定单个线程 * * 如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。 * 如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或者读锁,则申请的线程会一直等待释放写锁。 * @author * */public class MyReentrantReadWriteLock { private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); public static void main(String[] args) { final MyReentrantReadWriteLock test = new MyReentrantReadWriteLock(); new Thread(){ public void run() { test.get(Thread.currentThread()); test.write(Thread.currentThread()); }; }.start(); new Thread(){ public void run() { test.get(Thread.currentThread()); test.write(Thread.currentThread()); }; }.start(); } /** * 读操作,用读锁来锁定 * @param thread */ public void get(Thread thread) { rwl.readLock().lock(); try { long start = System.currentTimeMillis(); while(System.currentTimeMillis() - start <= 1) { System.out.println(thread.getName()+"正在进行读操作"); } System.out.println(thread.getName()+"读操作完毕"); } finally { rwl.readLock().unlock(); } } /** * 写操作,用写锁来锁定 * @param thread */ public void write(Thread thread) { rwl.writeLock().lock();; try { long start = System.currentTimeMillis(); while(System.currentTimeMillis() - start <= 1) { System.out.println(thread.getName()+"正在进行写操作"); } System.out.println(thread.getName()+"写操作完毕"); } finally { rwl.writeLock().unlock(); } }}运行结果:Thread-0正在进行读操作Thread-1正在进行读操作Thread-0正在进行读操作Thread-1正在进行读操作Thread-0正在进行读操作。。。Thread-1读操作完毕Thread-0读操作完毕Thread-0正在进行写操作Thread-0正在进行写操作Thread-0正在进行写操作Thread-0正在进行写操作Thread-0正在进行写操作。。。Thread-0写操作完毕Thread-1正在进行写操作Thread-1正在进行写操作Thread-1正在进行写操作Thread-1正在进行写操作。。。Thread-1写操作完毕结果分析:当两个线程获取的都是读锁的时候,读操作并发的进行,不会有线程进行等待,
当其中有线程需要获取写锁时,必须等待其他线程操作完成。
当其中有线程已经获取了写锁,其他线程必须等待当前线程写操作完成。
注意:
如果有一个线程已经占用了读锁,则此时其他线程如果要申请写锁,则申请写锁的线程会一直等待释放读锁。
如果有一个线程已经占用了写锁,则此时其他线程如果申请写锁或读锁,则申请的线程会一直等待释放写锁。
五、Lock与synchronized选择
1、Lock是一个接口,而synchronized是java中的关键字,synchronized是内置的语言实现。2、synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象的发生;而Lock在发生异常时,如果没有主动通过unLock去释放锁,则可能造成死锁现象,因此使用Lock时,需要在finally块中释放锁。3、Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断。4、通过Lock可以知道有没有成功获取锁,而synchronized无法办到。5、Lock可以提高多线程进行读操作的效率。在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized的,所以说,具体使用时要根据实际情况来选择。
- java同步:Lock
- 【java】同步,线程通信,lock
- Java同步与Lock接口
- Java 同步 synchronized与lock
- java线程同步 Lock同步锁
- Java 多线程 (PART XVII) Lock (I) Lock实现线程同步
- java 之 Lock 同步锁学习示例
- java多线程之Lock线程同步
- java线程第六课:同步锁Lock
- Java多线程同步之Lock用法
- Java Lock-同步的另一种实现
- Java线程同步synchronized,Lock,Condition
- Java中使用Lock控制线程同步
- java线程同步之Lock锁
- Java同步锁Lock的使用
- Java同步关键词synchronized和Lock接口
- java线程同步synchronized与lock
- java线程之线程同步与线程通信(Synchronized/Lock)
- poj 2018 斜率DP 求子序列的最大平均值
- 凯撒密码
- Error:The SDK Build Tools revision (23.0.3) is too low for project ':app'. Minimum required is 25.0.
- Intellij IDEA十大快捷键
- RBAC基础框架搭建
- java同步:Lock
- leetCode刷题归纳-Array(448. Find All Numbers Disappeared in an Array Add to List)
- 利用“4+1”视图建模方法进行软件架构设计
- Intellij IDEA 如何添加tab缩进
- 安卓开发环境搭建和第一个hello Android程序
- HttpClient总结
- NVIDIA Jetson TX1 系列开发教程之一:开箱测试
- [HDU2767]Proving Equivalences(Tarjan缩点)
- Unity3D学习:制作背包换装备UI