Java多线程编程之Lock用法实例

锁是控制多个线程对共享资源进行访问的工具。通常,锁提供了对共享资源的独占访问。一次只能有一个线程获得锁,对共享资源的所有访问都需要首先获得锁。不过,某些锁可能允许对共享资源并发访问,如 ReadWriteLock(维护了一对相关的锁,一个用于只读操作,另一个用于写入操作) 的读写锁。

1、Lock提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显式的。

public interface Lock{
  void lock(); //加锁
  //优先考虑响应中断,而不是响应锁定的普通获取或重入获取
  void lockInterruptibly() throws InterruptedException;
  boolean tryLock(); //可定时和可轮询的锁获取模式
  boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException;
  void unlock(); //解锁
  Condition newCondition();
}

2、ReentrantLock实现了lock接口,跟synchronized相比,ReentrantLock为处理不可用的锁提供了更多灵活性。
3、使用lock接口的规范形式要求在finally块中释放锁lock.unlock()。如果锁守护的代码在try块之外抛出了异常,它将永远不会被释放。

以下模拟Lock用法:假设有两个线程(A线程、B线程)去调用print(String name)方法,A线程负责打印'zhangsan'字符串,B线程负责打印'lisi'字符串。
1、当没有为print(String name)方法加上锁时,则会产生A线程还没有执行完毕,B线程已开始执行,那么打印出来的name就会出现如下问题。

2、当为print(String name)方法加上锁时,则会产生A执行完毕后,B线程才执行print(String name)方法,达到互斥或者说同步效果。

package com.ljq.test.thread;

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

/**
 * 用Lock替代synchronized
 *
 * @author Administrator
 *
 */
public class LockTest {

  public static void main(String[] args) {
    new LockTest().init();
  }

  private void init() {
    final Outputer outputer = new Outputer();
    //A线程
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(10);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          outputer.output("zhangsan");
        }

      }
    }).start();

    //B线程
    new Thread(new Runnable() {
      @Override
      public void run() {
        while (true) {
          try {
            Thread.sleep(10);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          outputer.output("lisi");
        }

      }
    }).start();

  }

  static class Outputer {
    Lock lock = new ReentrantLock();

    /**
     * 打印字符
     *
     * @param name
     */
    public void output(String name) {
      int len = name.length();
      lock.lock();
      try {
        for (int i = 0; i < len; i++) {
          System.out.print(name.charAt(i));
        }
        System.out.println();
      } finally {
        lock.unlock();
      }
    }
  }
}
时间: 2015-05-16

java Lock接口详解及实例代码

java  Lock接口 java.util.concurrent.locks 接口Lock public interface Loce Loce实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class IntegerDemo { public static void main

基于java中BlockingQueue的使用介绍

最近在维护一个java工程,在群里面也就聊起来java的优劣!无奈一些Java的终极粉丝,总是号称性能已经不必C++差,并且很多标准类库都是大师级的人写的,如何如何稳定等等.索性就认真研究一番,他们给我的一项说明就是,在线程之间投递消息,用java已经封装好的BlockingQueue,就足够用了. 既然足够用那就写代码测试喽,简简单单写一个小程序做了一番测试: 复制代码 代码如下: //默认包 import java.util.concurrent.*; import base.MyRunna

java多线程并发中使用Lockers类将多线程共享资源锁定

复制代码 代码如下: package com.yao; import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReadWriteLock;import java.util.c

SVN出现提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解决方案

SVN出现提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-locked dir解决方案 第一种方法: 通过svn插件来清理,首先选中项目,右键,选择team->refresh/cleanup即可.然后再更新文件就不会提示org.apache.subversion.javahl.ClientException: Attempted to lock an already-lockeddir了.但

详解Java多线程编程中LockSupport类的线程阻塞用法

LockSupport是用来创建锁和其他同步类的基本线程阻塞原语. LockSupport中的park() 和 unpark() 的作用分别是阻塞线程和解除阻塞线程,而且park()和unpark()不会遇到"Thread.suspend 和 Thread.resume所可能引发的死锁"问题. 因为park() 和 unpark()有许可的存在:调用 park() 的线程和另一个试图将其 unpark() 的线程之间的竞争将保持活性. 基本用法 LockSupport 很类似于二元信号

java中LinkedBlockingQueue与ArrayBlockingQueue的异同

相同: 1.LinkedBlockingQueue和ArrayBlockingQueue都实现了BlockingQueue接口: 2.LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列 内部都是使用ReentrantLock和Condition来保证生产和消费的同步: 当队列为空,消费者线程被阻塞:当队列装满,生产者线程被阻塞: 使用Condition的方法来同步和通信:await()和signal() 不同: 1.由上图可以看出,他们的锁机制不同 Li

java线程并发blockingqueue类使用示例

如果BlockingQueue是满的任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有新的空间才会被唤醒继续操作. BlockingQueue提供的方法主要有: add(anObject): 把anObject加到BlockingQueue里,如果BlockingQueue可以容纳返回true,否则抛出IllegalStateException异常. offer(anObject):把anObject加到BlockingQueue里,如果BlockingQueue

Java多线程编程之读写锁ReadWriteLock用法实例

读写锁:分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由jvm自己控制的,你只要上好相应的锁即可.如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁:如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁.总之,读的时候上读锁,写的时候上写锁! 三个线程读数据,三个线程写数据示例: 可以同时读,读的时候不能写,不能同时写,写的时候不能读. 读的时候上读锁,读完解锁:写的时候上写锁,写完解锁. 注意finally解锁. package com.ljq.test.th

详解Java多线程编程中互斥锁ReentrantLock类的用法

0.关于互斥锁 所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别: synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是

Java并发编程之显示锁ReentrantLock和ReadWriteLock读写锁

在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock. ReentrantLock概况 ReentrantLock是可重入的锁,它不同于内置锁, 它在每次使用都需要显示的加锁和解锁, 而且提供了更高级的特性:公平锁, 定时锁, 有条件锁, 可轮询锁, 可中断锁. 可以有效避免死锁的活跃性问题.ReentrantLock实现了 Lock接口: 复制代码 代码如下: public interface Lock {  

java集合框架 arrayblockingqueue应用分析

Queue ------------ 1.ArrayDeque, (数组双端队列) 2.PriorityQueue, (优先级队列) 3.ConcurrentLinkedQueue, (基于链表的并发队列) 4.DelayQueue, (延期阻塞队列)(阻塞队列实现了BlockingQueue接口) 5.ArrayBlockingQueue, (基于数组的并发阻塞队列) 6.LinkedBlockingQueue, (基于链表的FIFO阻塞队列) 7.LinkedBlockingDeque, (

深入Synchronized和java.util.concurrent.locks.Lock的区别详解

主要相同点:Lock能完成Synchronized所实现的所有功能.主要不同点:Lock有比Synchronized更精确的线程予以和更好的性能.Synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放.synchronized 修饰方法时 表示同一个对象在不同的线程中 表现为同步队列如果实例化不同的对象 那么synchronized就不会出现同步效果了.1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被

java线程阻塞中断与LockSupport使用介绍

上周五和周末,工作忙里偷闲,在看java cocurrent中也顺便再温故了一下Thread.interrupt和java 5之后的LockSupport的实现. 在介绍之前,先抛几个问题. Thread.interrupt()方法和InterruptedException异常的关系?是由interrupt触发产生了InterruptedException异常? Thread.interrupt()会中断线程什么状态的工作? RUNNING or BLOCKING? 一般Thread编程需要关注

深入Java线程中断的本质与编程原则的概述

在历史上,Java试图提供过抢占式限制中断,但问题多多,例如前文介绍的已被废弃的Thread.stop.Thread.suspend和 Thread.resume等.另一方面,出于Java应用代码的健壮性的考虑,降低了编程门槛,减少不清楚底层机制的程序员无意破坏系统的概率. 如今,Java的线程调度不提供抢占式中断,而采用协作式的中断.其实,协作式的中断,原理很简单,就是轮询某个表示中断的标记,我们在任何普通代码的中都可以实现. 例如下面的代码:    volatile bool isInter

Java线程中断的本质深入理解

一.Java中断的现象 首先,看看Thread类里的几个方法: public static boolean interrupted 测试当前线程是否已经中断.线程的中断状态 由该方法清除.换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外). public boolean isInterrupted() 测试线程是否已经中断.线程的中断状态 不受该方法的影响. public void in

如何实现Java线程安全问题

这篇文章主要介绍了如何实现Java线程安全问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 解决线程安全问题的第一种方案:使用同步代码块 格式: synchronized(锁对象) { 可能会出现线程安全问题的代码(访问了共享数据的代码) } 注意:代码块中的锁对象,可以是任意对象,但必须保证多个线程之间使用的是同一个 锁对象的作用是把同步代码块锁住,同一时间只能让一个线程在同步代码块中执行 package com.fgy.demo02; /

java 线程同步详细介绍及实例代码

java 线程同步 概要: 为了加快代码的运行速度,我们采用了多线程的方法.并行的执行确实让代码变得更加高效,但随之而来的问题是,有很多个线程在程序中同时运行,如果它们同时的去修改一个对象,很可能会造成讹误的情况,这个时候我们需要用一种同步的机制来管理这些线程. (一)竞争条件 记得操作系统中,让我印象很深的有一张图.上面画的是一块块进程,在这些进程里面分了几个线程,所有这些线程齐刷刷统一的指向进程的资源.Java中也是如此,资源会在线程间共享而不是每个线程都有一份独立的资源.在这种共享的情况下

浅析java线程中断的办法

中断线程相关的方法 中断线程有一些相应的方法,这里列出来一下. 注意,如果是Thread.method(),则代表是静态方法.如果是thread.method()则代表着是类方法 void thread.stop() 这个方法能中断正在运行的线程,但是已经不推荐使用了,在将来的版本或许弃用,因为强行中断运行中的线程,是不安全的. void thread.interrupt() 如果正在运行wait(),sleep(),join()这三个方法阻塞了线程,那么将会使得线程抛出InterruptedE

创建并运行一个java线程方法介绍

要解释线程,就必须明白什么是进程. 什么是进程呢? 进程是指运行中的应用程序,每个进程都有自己独立的地址空间(内存空间),比如用户点击桌面的IE浏览器,就启动了一个进程,操作系统就会为该进程分配独立的地址空间.当用户再次点击左面的IE浏览器,又启动了一个进程,操作系统将为新的进程分配新的独立的地址空间.目前操作系统都支持多进程. 要点:用户每启动一个进程,操作系统就会为该进程分配一个独立的内存空间. 线程--概念 在明白进程后,就比较容易理解线程的概念. 什么是线程呢? 是进程中的一个实体,是被

浅谈Java线程Thread之interrupt中断解析

这一篇我们说说Java线程Thread的interrupt中断机制. 中断线程 线程的thread.interrupt()方法是中断线程,将会设置该线程的中断状态位,即设置为true,中断的结果线程是死亡.还是等待新的任务或是继续运行至下一步,就取决于这个程序本身.线程会不时地检测这个中断标示位,以判断线程是否应该被中断(中断标示值是否为true).它并不像stop方法那样会中断一个正在运行的线程. 判断线程是否被中断 判断某个线程是否已被发送过中断请求,请使用Thread.currentThr

Java阻塞队列四组API介绍(小结)

通过前面几篇文章的学习,我们已经知道了Java中的队列分为阻塞队列和非阻塞队列以及常用的七个阻塞队列.如下图: 本文来源:凯哥Java(kaigejava)讲解Java并发系列之阻塞队列教程.系列文章,欢迎大家从第一篇文章开始看起. 在查看以上七个队列的API的时候,我们可以很明显的看到以下四组API: add()/remove()/remove offer()/poll()/peek() put/take() offer(e,time,unit)/poll(time,unit). 分别对应的是