Java同步锁
2016-07-26 17:44
411 查看
同步机制关键字synchronized
可以锁对象、函数、class(类)、代码块。每个对象都只有一个锁。synchronized作用于函数时,实际上锁的也是对象。public class SynchronizedDemo { //同步方法(锁的是对象) public synchronized void syncMethd() { } //同步对象(锁的是对象) public void syncThis() { synchronized(this){ } } //同步类(锁的是class对象) public void syncClassMethod() { synchronized (SynchronizedDemo.class) { } } //同步静态方法(锁的是class对象) public synchronized static void syncStaticMethiod() { } }
显示锁ReentrantLock与Condition
和内置锁synchronized相比:1. 获取和释放的灵活性
2. 轮询锁和定时锁
3. 公平性
内置锁synchronized的获取和释放都在同一个代码块中,而显示锁则可以将锁的获得和释放分开。同时,显示锁可以提供轮询锁和定时锁,也可提供公平锁和非公平锁。
基本操作:
函数 | 作用 |
---|---|
lock | 获取锁 |
tryLock | 尝试获取锁 |
tryLock(long timeout,TimeUnit unit0 | 尝试获取锁,如果指定时间还没获获取到,则超时 |
unlock | 释放锁 |
newCondition | 获取锁的Condition |
Lock lock = new ReentrantLock(); private void perform() { lock.lock(); try { } finally { lock.unlock(); } }
lock必须在finally块中释放,否则,如果受保护的代码抛出异常,锁就有可能永远得不到释放!
newCondition方法用来获取Lock上的一个条件,Condition与Lock是绑定的,Condition用于实现线程间通信。用于实现类似于wait、notify、notifyAll的功能。
基本操作:
函数 | 作用 |
---|---|
await | 线程等待 |
await(int time,TimeUnit unit) | 线程等待特定时间,超过时间则为超时 |
signal | 随机唤醒某个等待线程 |
signalAll | 唤醒所有等待线程 |
/** Main lock guarding all access */ final ReentrantLock lock; /** Condition for waiting takes */ private final Condition notEmpty; /** Condition for waiting puts */ private final Condition notFull; public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; //创建锁,fair表示是公平锁还是非公平锁 lock = new ReentrantLock(fair); //创建列表非空的Condition notEmpty = lock.newCondition(); //创建列表未满的Condition notFull = lock.newCondition(); } public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) //队列已满,不满的条件等待 notFull.await(); insert(e); } finally { lock.unlock(); } } public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == 0) //列表为0,以非空条件挂起该线程 notEmpty.await(); return extract(); } finally { lock.unlock(); } }
volatile
相关阅读:volatile的适用场景、
java中volatile关键字的含义
信号量Semaphore
是一个计数信号量,本质是一个“共享锁”。信号量维护了一个信号量许可集,线程可以通过调用acquire获取信号量的许可。通过release释放它持有的信号量。public class SemaphoneDemo { static int time = 0; public static void main(String[] args) { final ExecutorService executorService = Executors.newFixedThreadPool(3); final Semaphore semaphore = new Semaphore(3); for (int i = 0; i < 5; i++) { executorService.submit(new Runnable() { @Override public void run() { try { semaphore.acquire(); System.out.println("the rest of the semaphone "+semaphore.availablePermits()); Thread.sleep(2000); semaphore.release(); } catch (InterruptedException e) { e.printStackTrace(); } } }); } } }
循环栅栏CyclicBarrier
同步辅助类,允许一组线程相互等待,直到达到某个公共屏障点。因为该barrier在释放等待线程后可以重用,所以它称为循环的barrierpublic class CyclicBarrierDemo { private static final int SIZE = 5; private static CyclicBarrier mCyclicBarrier; public static void main(String[] args) { mCyclicBarrier = new CyclicBarrier(SIZE,new Runnable() { @Override public void run() { System.out.println("now all the five thread catch the CylicBarrier, you have condition to perform sth. the one: "+mCyclicBarrier.getParties()); } }); for (int i = 0; i <SIZE; i++) { new WorkerThread().start(); } } static class WorkerThread extends Thread{ public void run() { System.out.println(Thread.currentThread().getName()+" waitting CyclicBarrier"); try { //let this thread catch the mCyclicBarrier mCyclicBarrier.await(); //when all the five thread catch the mCyclicBarrier,then continue System.out.println(Thread.currentThread().getName()+" continue"); } catch (InterruptedException e) { e.printStackTrace(); } catch (BrokenBarrierException e) { e.printStackTrace(); } } } }
运行结果:
创建CyclicBarrier时,第一个参数为一组线程的个数,需要达到的个数( 调用mCyclicBarrier.await()线程的个数),线程们才会继续往下执行;第二个参数为一个Runnable对象,当线程达到指定个数时,会先执行这个任务,然后所有的线程才会继续执行。
闭锁CountDownLatch
同步辅助类,在一组线程(这些线程都要注入闭锁对象,执行完任务,CountDownLatch对象的countDown方法,表示任务数减一)执行完前,让一个或多个线程等待。public class CountDownLatchDemo { private static int LATCH_SIZE = 5; public static void main(String[] args) { CountDownLatch latch = new CountDownLatch(LATCH_SIZE); for (int i = 0; i < LATCH_SIZE; i++) { new WorkerThread(latch).start(); } System.out.println("main thread wait"); //wait the task complete(five thread complete their duty) try { latch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("man thread continue"); } static class WorkerThread extends Thread{ private CountDownLatch mLatch; public WorkerThread(CountDownLatch mLatch) { this.mLatch = mLatch; } @Override public void run() { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName()+ " perform"); //decrease the number of latch mLatch.countDown(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
执行结果:
CyclicBarrier和CountDownLatch的区别
1. (CyclicBarrier和CountDownLatch在构造时都会传入一个int类型的参数,代表线程个数N)CyclicBarrier是让N个线程相互等待,CountDownLatch是让1个或M个线程等待N个线程执行完。重点的是CountDownLatch要等其他线程执行完(强行礼让别人,或者可能要等他们释放资源),而CyclicBarrier都是一群半吊子,半吊子够数了就放行。
2. CyclicBarrier计数器可以被重置后使用,CountDownLatch不可以。
推荐阅读:
1、鸿洋的Java并发专题,强烈推荐!
2、聊聊并发系列
聊聊并发(一)深入分析Volatile的实现原理聊聊并发(二)Java SE1.6中的Synchronized
聊聊并发(三)Java线程池的分析和使用
聊聊并发(四)深入分析ConcurrentHashMap
聊聊并发(五)原子操作的实现原理
聊聊并发(六)ConcurrentLinkedQueue的实现原理分析
聊聊并发(七)——Java中的阻塞队列
聊聊并发(八)——Fork/Join框架介绍
聊聊并发(十)生产者消费者模式
3、并发编程系列:
Java并发编程(1):可重入内置锁Java并发编程(2):线程中断(含代码)
Java并发编程(3):线程挂起、恢复与终止的正确方法(含代码)
Java并发编程(4):守护线程与线程阻塞的四种情况
Java并发编程(5):volatile变量修饰符—意料之外的问题(含代码)
Java并发编程(6):Runnable和Thread实现多线程的区别(含代码)
Java并发编程(7):使用synchronized获取互斥锁的几点说明
Java并发编程(8):多线程环境中安全使用集合API(含代码)
Java并发编程(9):死锁(含代码)
Java并发编程(10):使用wait/notify/notifyAll实现线程间通信的几点重要说明
Java并发编程(11):线程间通信中notify通知的遗漏(含代码)
Java并发编程(12):线程间通信中notifyAll造成的早期通知问题(含代码)
Java并发编程(13):生产者—消费者模型(含代码)
Java并发编程(14):图文讲述同步的另一个重要功能—内存可见性
Java并发编程(15):并发编程中实现内存可见的两种方法比较—加锁和volatile变量
Java并发编程(16):深入Java内存模型—happen-before规则及其对DCL的分析(含代码)
Java并发编程(17):深入Java内存模型—内存操作规则总结
Java并发编程(18):第五篇中volatile意外问题的正确分析解答(含代码)
Java并发编程(19):并发新特性—Executor框架与线程池(含代码)
Java并发编程(20):并发新特性—Lock锁和条件变量(含代码)
4、其他
Java多线程深度探索为什么volatile不能保证原子性而Atomic可以?
Java内存模型(JSR133)问与答
JAVA CAS原理深度分析
CLH队列锁
ReentrantLock实现原理深入探究
Lock 锁与条件变量
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序